分享
  1. 首页
  2. 文章

[go语言]利用缓冲信道来实现网游帐号验证消息的分发和等待

stevewang · · 3852 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

设想这样一个应用场景:一个网游登录服务器的实现里,每个玩家的连接用一个goroutine来处理,有一个主动对象AccountServer代表帐号服务器,AccountServer会接收每个玩家的请求发送给帐号服务器验证合法性,然后把返回的结果分发给各个玩家。同时每个玩家goroutine在等待帐号验证的过程中需要阻塞等待
利用缓冲信道可以比较容易地实现这个特性。以下就是大致的代码结构,其中SendAndReceive函数玩家goroutine调用并阻塞等待结果。该函数中利用缓冲信道来获取一个用于获得结果的信道,使用之后再回收。

typeMsgstruct{
    data[]byte
    chchan[]byte
}
type Connection interface{
    Write([]byte)
    Read()[]byte
}
typeAccountServerstruct{
    conn Connection //与帐号数据库服务器的网络链接
    tokenschanchan[]byte
    msgchanMsg
}
funcNewAccountServer(conn Connection,maxclientcountint)*AccountServer{
    p:=&AccountServer{}
    p.conn = conn 
    p.tokens=make(chanchan[]byte,maxclientcount)
    p.msg=make(chanMsg,maxclientcount)
    fori:=0;i<maxclientcount;i++{
        p.tokens<-make(chan[]byte)
    }
    gop.run()
    returnp
}
func(p*AccountServer)run(){
    rch:=make(chan[]byte)
    sch:=make(chan[]byte)
    gofunc(){
        for{p.conn.Write(<-sch)}
    }()
    gofunc(){
        for{rch<-p.conn.Read()}
    }()
    p.manage(sch,rch)
}
func(p*AccountServer)manage(schchan<-[]byte,rch<-chan[]byte){
    variduint32
    players:=make(map[uint32]chan[]byte)
    for{
        select{
        casemsg:=<-p.msg:
            id++
            //在数据包前面附上一个uint32,用于标识发送数据的玩家
            buff:=make([]byte,4+len(msg.data))
            buff[0]=byte(id&0xff)
            buff[1]=byte((id>>8)&0xff)
            buff[2]=byte((id>>16)&0xff)
            buff[3]=byte((id>>24)&0xff)
            copy(buff[4:],msg.data)
            sch<-buff
            players[id]=msg.ch
        casedata:=<-rch:
            iflen(data)<=4{
                break
            }
            //从帐号数据库服务器返回的数据前四个字节会附带同样的uint32,,用于标识玩家
            varkeyuint32
            key=uint32(data[0])
            key|=uint32(data[1])<<8
            key|=uint32(data[2])<<16
            key|=uint32(data[3])<<24
            ch,ok:=players[key]
            ifok{
         ch <- data[4:]
       }
     }
    }
}
// 玩家对应的goroutine调用此函数向帐号服务器发送数据并等待返回
func (p *AccountServer) SendAndReceive(data []byte) []byte {
//获取一个用于获取返回数据的信道
ch:=<-p.tokens
//回收信道
deferfunc(){p.tokens<-ch}()
p.msg<-Msg{data,ch}
return<-ch
}

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
3852 次点击
1 回复 | 直到 2000年01月01日 00:00:00
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏