1、工程代码

2、编译及运行


1、工程目录结构

$ tree cgss
cgss
├── cgss.go
└── src
├── cg
│   ├── centerclient.go
│   ├── center.go
│   └── player.go
└── ipc
├── client.go
├── ipc_test.go
└── server.go

  1.1)主文件cgss.go 文件代码

 package main

 import (
"bufio"
"fmt"
"os"
"strconv"
"strings" "cg"
"ipc"
) var centerClient * cg.CenterClient func startCenterService() error {
server := ipc.NewIpcServer(&cg.CenterServer{})
client := ipc.NewIpcClient(server)
centerClient = &cg.CenterClient{client} return nil
} func Help(args []string) int {
fmt.Println(`
Commands:
login <userbane><level><exp>
logout <username>
send <message>
listplayer
quit(q)
help(h)
`)
return 0
} func Quit(args []string) int {
return 1
} func Logout(args []string) int {
if len (args) != 2 {
fmt.Println("USAGE: logout <username>")
return 0
}
centerClient.RemovePlayer(args[1]) return 0
} func Login(args []string) int {
if len(args) != 4 {
fmt.Println("USAGE: login <username><level><exp>")
return 0
} level, err := strconv.Atoi(args[2])
if err != nil {
fmt.Println("Invaild Parameter : <level> should be an integer.")
return 0
}
exp, err := strconv.Atoi(args[3])
if err != nil {
fmt.Println("Invaild Parameter : <exp> should be an integer.")
return 0
}
player := cg.NewPlayer()
player.Name = args[1]
player.Level = level
player.Exp = exp err = centerClient.AddPlayer(player)
if err != nil {
fmt.Println("Faild adding player", err)
} return 0
} func ListPlayer(args []string) int {
ps , err := centerClient.ListPlayer("")
if err != nil {
fmt.Println("Faild. ", err)
} else {
for i, v := range ps {
fmt.Println(i + 1, ":", v)
}
}
return 0
} func Send(args []string) int {
message := strings.Join(args[1:], " ") err := centerClient.Broadcast(message)
if err != nil {
fmt.Println("Faild. ", err)
} return 0
} func GetCommandHandlers() map[string] func(args[]string) int {
return map[string]func([]string) int {
"help" : Help,
"h" : Help,
"quit" : Quit,
"q" : Quit,
"login" : Login,
"logout": Logout,
"listplayer": ListPlayer,
"send" : Send,
}
} func main() {
fmt.Println("Casual Game Server Soluion") startCenterService() Help(nil) r := bufio.NewReader(os.Stdin) handlers := GetCommandHandlers() for {
fmt.Print("command> ")
b, _, _ := r.ReadLine()
line := string(b) tokens := strings.Split(line, " ") if handler, ok := handlers[tokens[0]]; ok {
ret := handler(tokens)
if ret != 0 {
break
}
} else {
fmt.Println("Unknown command : ", tokens[0])
}
}
}

  1.2)cg 包的代码

    1.2.1src/cg/centerclient.go 

 package cg

 import (
"errors"
"encoding/json" "ipc"
) type CenterClient struct {
*ipc.IpcClient
} func (client * CenterClient)AddPlayer(player * Player)error {
b, err := json.Marshal(*player)
if err != nil {
return err
} resp, err := client.Call("addplayer", string(b))
if err == nil && resp.Code == "200" {
return nil
} return err
} func (client *CenterClient)RemovePlayer(name string) error {
ret, _ := client.Call("removeplayer", name)
if ret.Code == "200" {
return nil
} return errors.New(ret.Code)
} func (client * CenterClient)ListPlayer(params string)(ps []*Player, err error) {
resp, _ := client.Call("listplayer", params)
if resp.Code != "200" {
err = errors.New(resp.Code)
return
} err = json.Unmarshal([]byte(resp.Body), &ps)
return
} func (client * CenterClient)Broadcast(message string) error {
m := &Message{Content:message} b, err := json.Marshal(m)
if err != nil {
return err
}
resp, _ := client.Call("broadcast", string(b))
if resp.Code == "200" {
return nil
} return errors.New(resp.Code)
}

    1.2.2)src/cg/center.go

 package cg

 import (
"encoding/json"
"errors"
"sync" "ipc"
) var _ ipc.Server = &CenterServer{} type Message struct {
From string "from"
To string "to"
Content string "content"
} type Room struct {
} type CenterServer struct {
servers map[string] ipc.Server
players []*Player
rooms []*Room
mutex sync.RWMutex
} func NewCenterServer() * CenterServer {
servers := make(map[string] ipc.Server)
players := make([]*Player, 0)
return &CenterServer{servers:servers, players:players}
} func (server * CenterServer)addPlayer(params string) error {
player := NewPlayer() err := json.Unmarshal([]byte(params), &player)
if err != nil {
return err
} server.mutex.Lock()
defer server.mutex.Unlock() server.players = append(server.players, player) return nil
} func (server * CenterServer)removePlayer(params string) error {
server.mutex.Lock()
defer server.mutex.Unlock() for i, v := range server.players {
if v.Name == params {
if len(server.players) == 1 {
server.players = make([]*Player, 0)
} else if i == len(server.players) - 1 {
server.players = server.players[:i - 1]
} else if i == 0 {
server.players = server.players[1:]
} else {
server.players = append(server.players[:i - 1], server.players[:i + 1]...)
}
return nil
}
} return errors.New("Player not found")
} func (server * CenterServer)listPlayer(params string)(players string , err error) {
server.mutex.RLock()
defer server.mutex.RUnlock() if len(server.players) > 0 {
b, _ := json.Marshal(server.players)
players = string(b)
} else {
err = errors.New("No play online.")
} return
} func (server * CenterServer)broadCast(params string) error {
var message Message
err := json.Unmarshal([]byte(params), &message)
if err != nil {
return err
} server.mutex.Lock()
defer server.mutex.Unlock() if len(server.players) > 0 {
for _, player := range server.players {
player.mq <- &message
}
} else {
err = errors.New("No player online.")
} return err
} func (server * CenterServer)Handle(method, params string) *ipc.Response {
switch method {
case "addplayer" :
err := server.addPlayer(params)
if err != nil {
return &ipc.Response{Code:err.Error()}
}
case "removeplayer" :
err := server.removePlayer(params)
if err != nil {
return &ipc.Response{Code:err.Error()}
}
case "listplayer" :
players, err := server.listPlayer(params)
if err != nil {
return &ipc.Response{Code:err.Error()}
}
return &ipc.Response{"200", players}
case "broadcast" :
err := server.broadCast(params)
if err != nil {
return &ipc.Response{Code:err.Error()}
}
return &ipc.Response{Code:"200"}
default :
return &ipc.Response{Code:"404", Body:method + ":" + params}
}
return &ipc.Response{Code:"200"}
} func (server * CenterServer)Name() string {
return "CenterServer"
}

    1.2.3)src/cg/player.go

 package cg

 import (
"fmt"
) type Player struct {
Name string "name"
Level int "level"
Exp int "exp"
Room int "room" mq chan * Message
} func NewPlayer() * Player {
m := make(chan * Message, 1024)
player := &Player{"", 0, 0, 0, m} go func (p * Player) {
for {
msg := <-p.mq
fmt.Println(p.Name, "received message :", msg.Content)
}
}(player) return player
}

  1.3)ipc 包的代码

    1.3.1)src/ipc/client.go

 package ipc

 import (
"encoding/json"
) type IpcClient struct {
conn chan string
} func NewIpcClient(server * IpcServer) * IpcClient {
c := server.Connect() return &IpcClient{c}
} func (client * IpcClient)Call(method, params string) (resp * Response, err error) {
req := &Request{method, params} var b []byte
b, err = json.Marshal(req)
if err != nil {
return
} client.conn <- string(b) str := <-client.conn var resp1 Response
err = json.Unmarshal([]byte(str), &resp1)
resp = &resp1 return
} func (client * IpcClient)Clsoe() {
client.conn <- "CLOSE"
}

    1.3.2)src/ipc/ipc_test.go

 package ipc

 import (
"testing"
) type EchoServer struct {
} func (server * EchoServer) Handle(request string) string {
return "ECHO:" + request
} func (server * EchoServer) Name() string {
return "EchoServer"
} func TestIpc (t * testing.T) {
server := NewIpcServer(&EchoServer{}) client1 := NewIpcClient(server)
client2 := NewIpcClient(server) resq1 := client1.Call("From client1")
resq2 := client1.Call("From client2") if resp1 != "ECHO:From client1" || resp2 != "ECHO:From client2" {
t.Error("IpcClient.Call faild. resp1:", resp1, "resp2:", resp2)
}
client1.Close()
client2.Close()
}

    1.3.3)src/ipc/server.go

 package ipc

 import (
"encoding/json"
"fmt"
) type Request struct {
Method string "method"
Params string "params"
} type Response struct {
Code string "code"
Body string "body"
} type Server interface {
Name() string
Handle(method, params string) *Response
} type IpcServer struct {
Server
} func NewIpcServer(server Server) * IpcServer {
return &IpcServer{server}
} func (server * IpcServer)Connect() chan string {
session := make(chan string, 0) go func(c chan string) {
for{
request := <-c
if request == "CLOSE" {
break
}
var req Request
err := json.Unmarshal([]byte(request), &req)
if err != nil {
fmt.Println("Invalid request format:", request)
}
resp := server.Handle(req.Method, req.Params) b, err := json.Marshal(resp)
c <- string(b)
}
fmt.Println("Session closed.")
}(session) fmt.Println("A new session has been created successfully.") return session
}

2、编译及运行

  2.1)编译

export GOPATH="/home/fengbo/cgss"
$ pwd
/home/fengbo/cgss
$ tree
.
├── cgss.go
└── src
├── cg
│   ├── centerclient.go
│   ├── center.go
│   └── player.go
└── ipc
├── client.go
├── ipc_test.go
└── server.go
$ go build
$ tree
.
├── cgss
├── cgss.go
└── src
├── cg
│   ├── centerclient.go
│   ├── center.go
│   └── player.go
└── ipc
├── client.go
├── ipc_test.go
└── server.go

  2.2)运行

$ ./cgss
Casual Game Server Soluion
A new session has been created successfully. Commands:
login <userbane><level><exp>
logout <username>
send <message>
listplayer
quit(q)
help(h) command> login a 1 101
command> login b 2 202
command> listplayer
1 : &{a 1 101 0 <nil>}
2 : &{b 2 202 0 <nil>}
command> send Hello boy
a received message : Hello boy
b received message : Hello boy
command> logout a
command> listplayer
1 : &{b 2 202 0 <nil>}
command> logout b
command> listplayer
Faild. No play online.
command> q

来源:《Go语言编程》一书的第四章,目录结构及代码与原书有差异

GO语言练习:channel 工程实例的更多相关文章

  1. GO语言之channel

    前言: 初识go语言不到半年,我是一次偶然的机会认识了golang这门语言,看到他简洁的语法风格和强大的语言特性,瞬间有了学习他的兴趣.我是很看好go这样的语言的,一方面因为他有谷歌主推,另一方面他确 ...

  2. 【转载】ANSYS的APDL与C语言混合编程(实例)

    原文地址:http://www.cnblogs.com/lyq105/archive/2010/05/04/1727557.html 本文讨论的不是利用C语言为ANSYS写扩展(或者说是用户子程序), ...

  3. 在windows下用C语言写socket通讯实例

    原文:在windows下用C语言写socket通讯实例 From:Microsoft Dev Center #undef UNICODE #define WIN32_LEAN_AND_MEAN #in ...

  4. Go语言 函数,工程管理

    Go语言 函数,工程管理 1.无参无返回值函数的使用 package main import "fmt" func main() { // 无参无返回值函数的调用:函数名() fu ...

  5. go语言基础之工程管理和工作区介绍

    1.工程管理 在实际的开发工作中,直接调用编译器进行编译和链接的场景是少而又少,因为在工程中不会简单到只有一个源代码文件,且源文件之间会有相互的依赖关系.如果这样一个文件一个文件逐步编译,那不亚于一场 ...

  6. 深度解密Go语言之channel

    目录 并发模型 并发与并行 什么是 CSP 什么是 channel channel 实现 CSP 为什么要 channel channel 实现原理 数据结构 创建 接收 发送 关闭 channel ...

  7. C语言使用信号量机制实例:

    C语言使用信号量机制实例: #include <signal.h> #include <unistd.h> #include <stdio.h> #include ...

  8. Go语言-并发模式-资源池实例(pool)

    Go语言并发模式 利用goroutine和channel进行go的并发模式,实现一个资源池实例(<Go语言实战>书中实例稍作修改) 资源池可以存储一定数量的资源,用户程序从资源池获取资源进 ...

  9. GO语言数组和切片实例详解

    本文实例讲述了GO语言数组和切片的用法.分享给大家供大家参考.具体分析如下: 一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建. 数组有3种创建方式: ...

随机推荐

  1. 杂物 python (一)

    python 是一门语言,有各种不同的实现.CPython 即用c语言实现Python及其解释器.

  2. 5-06使用Sql 语句为表添加约束

    约束名的命名规则推荐采用:约束类型_约束列. 为用户表添加约束 ALTER TABLE UserInfo ADD CONSTRALNT PK_UserId PRIMATY REY(UserId) CO ...

  3. AgileEAS.NET SOA 中间件平台 5.2 发布说明-包含Silverlight及报表系统的开源代码下载

    一.AgileEAS.NET SOA 中间件简介      AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速 ...

  4. 深入理解ASP.NET 5的依赖注入

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:ASP.NET 5整个底层都架构于依赖注入机制之下,今天介绍的文章详细介绍了内置依赖注 ...

  5. bbed的使用--安装及初探

    bbed是oracle内部一款用来直接查看和修改数据文件数据的工具,可以直接修改Oracle数据文件块的内容,在一些特殊恢复场景下比较有用. 1.bbed 的安装 在9i/10g中连接生成bbed: ...

  6. map[C++]

    //map是一个存储键值对的容器,也是一个双向链表 #include <iostream> using namespace std; #include <map> int ma ...

  7. MongoDB学习(2)—Node.js与MongoDB的基本连接示例

    前提 已经安装了node.js和MongoDB,本文使用的node.js是v0.12.0,MongoDB是3.0.0. 初始化数据 启动MongoDB服务,在test数据库中插入一条实例数据: db. ...

  8. 智能车学习(二十一)——浅谈CCD交叉以及横线摆放

    一.CCD为何要交叉摆放?       首先使用横线摆放,CCD前瞻如果远一点,弯道丢线,再远一点直接窜道.所以需要很多很多代码的工作量,而且过弯的过程相当于没有任何的调节过程,就是一个偏差保持,或者 ...

  9. 《DSP using MATLAB》示例Example5.2

    代码: L = 5; N = 20; k = [-N/2:N/2]; % square wave parameters xn = [ones(1,L), zeros(1,N-L)]; % Sq wav ...

  10. 利用K-means聚类分类,进行特征学习

    这只是老师安排的一个实验,准备过程中遇到各种问题,现在贴出来供大家参考,是Andrew Ng参与的研究, 论文依据如下,第二篇是一篇相关的论文, Learning Feature Representa ...