[go语言]利用缓冲信道来实现网游帐号验证消息的分发和等待
type Msg struct {
data []byte
ch chan []byte
}
typeConnection interface {
Write([]byte)
Read() []byte
}
type AccountServer struct {
conn Connection // 与帐号数据库服务器的网络链接
tokens chan chan []byte
msg chan Msg
}
func NewAccountServer(connConnection, maxclientcount int) *AccountServer {
p := &AccountServer{}
p.conn = conn
p.tokens = make(chan chan []byte, maxclientcount)
p.msg = make(chan Msg, maxclientcount)
for i := 0; i < maxclientcount; i++ {
p.tokens <- make(chan []byte)
}
go p.run()
return p
}
func (p *AccountServer) run() {
rch := make(chan []byte)
sch := make(chan []byte)
go func() {
for {p.conn.Write(<-sch)}
}()
go func() {
for {rch <- p.conn.Read()}
}()
p.manage(sch, rch)
}
func (p *AccountServer) manage(sch chan<- []byte, rch <-chan []byte) {
var id uint32
players := make(map[uint32]chan []byte)
for {
select {
case msg := <-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
case data := <-rch:
if len(data) <= 4 {
break
}
// 从帐号数据库服务器返回的数据前四个字节会附带同样的uint32,,用于标识玩家
var key uint32
key = uint32(data[0])
key |= uint32(data[1]) << 8
key |= uint32(data[2]) << 16
key |= uint32(data[3]) << 24
ch, ok := players[key]
if ok {
ch <- data[4:]
}
}
}
}
func (p *AccountServer) SendAndReceive(data []byte) []byte {
// 获取一个用于获取返回数据的信道
ch := <-p.tokens
// 回收信道
defer func() { p.tokens <- ch }()
p.msg <- Msg{data, ch}
return <-ch
}
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。