[TOC]
定义结构体 // 在src/server/msg/lobby.proto下定义结构体 在script/protocol/lobby.proto下定义结构体 ChatREQ // 消息发送 ChatACK // 消息送达
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 message UserBaseInfo{ string Uid = 1 ; string NickName = 2 ; string Avatar = 3 ; } message ChatMessage{ string Type = 1 ; string ContentJson = 2 ; } message ChatREQ { ChatMessage Message=1 ; uint32 ToId=2 ; string ToType=3 ; } message ChatACK { UserBaseInfo From=1 ; ChatMessage Message=2 ; uint32 ToId=3 ; string ToType=4 ; }
生成**.pb.go ps:需要本机有protobuf环境安装
1 2 protoc --proto_path =IMPORT_PATH --go_out =DST_DIR path/to /file.proto
目前我是放在当前目录下面的 在src/server/msg目录下执行
1 protoc --go_out= ./ *.proto
如果是给php用的
1 2 protoc --php_out= ./ *.proto
注册到消息处理器 src/server/msg/msg.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package msgimport ( "github.com/name5566/leaf/network/protobuf" ) var Processor = protobuf.NewProcessor()func init () { Processor.Register(&Test{}) Processor.Register(&UserLogin{}) Processor.Register(&UserRegister{}) Processor.Register(&UserResult{}) Processor.Register(&UserST{}) Processor.Register(&ChatREQ{}) Processor.Register(&ChatACK{}) }
在路由中监听ChatREQ src/server/gate/router.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package gateimport ( "server/game" "server/msg" ) func init () { msg.Processor.SetRouter(&msg.Test{}, game.ChanRPC) msg.Processor.SetRouter(&msg.UserLogin{}, game.ChanRPC) msg.Processor.SetRouter(&msg.UserRegister{}, game.ChanRPC) msg.Processor.SetRouter(&msg.ChatREQ{}, game.ChanRPC) }
在handle中进行业务处理 src/server/game/internal/handler.go
1 2 3 4 5 6 7 func init () { handler(&msg.Test{}, handleTest) handler(&msg.UserLogin{}, handleUserLogin) handler(&msg.UserRegister{}, handleUserRegister) handler(&msg.ChatREQ{}, handleChatREQ) }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 func handleChatREQ (args []interface {}) { m := args[0 ].(*msg.ChatREQ) a := args[1 ].(gate.Agent) log.Debug("receive GetMessage message:%v" , m.GetMessage()) myInfo := &msg.UserBaseInfo{ Uid:"11" , NickName:"张三" , Avatar:"sss.png" , } retBuf := &msg.ChatACK{ From : myInfo, Message : m.GetMessage(), ToId : m.GetToId(), ToType : m.GetToType(), } a.WriteMsg(retBuf) }
客户端用相同的lobby.proto去生成protocol.js ps需客户端安装protobufjs
1 npm install -g protobufjs
在所在目录执行以下命令生成protocol.js
1 pbjs -t static -module -w commonjs -o protocol.js lobby.proto
修改文件内的
1 2 // var $protobuf = require("protobufjs/minimal" );var $protobuf = window.protobuf;
把protocol.js转成ts的
1 pbts -o protocol .d .ts protocol .js
客户端发送消息 1 2 3 messageservice.ready(()=> { messageservice.sendChatTest() })
1 2 3 4 public sendChatTest ( ) { console .log('=====sendChatTest' ) this ._sendBuffMsg('ChatREQ' ,{Message :{'Type' :'text' ,'ContentJson' :'{text:"laiba"}' },ToId :123 ,ToType :"chat" }) }
1 2 3 4 5 6 7 8 9 private _sendBuffMsg (proName:string ,data:{} ) { let msgid = WebsocketService.ProtocolId[proName] let message = msg[proName].create(data); let buffer = msg[proName].encode(message).finish(); let addtag_buffer = WebsocketService.protoBufAddtag(msgid,buffer); this .ws.send(addtag_buffer) }
客户端接受消息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 export class WebsocketService { public ws:WebSocket static ProtocolId={ Test:0 , ChatREQ:5 , ChatACK:6 , } private offline_callback_arr:Array <Function >; constructor ( ) { this .offline_callback_arr = [] this .init(); } private init ( ) { let self = this let ws = new WebSocket("ws://x.x.x.x:3653" ); this .ws = ws ws.binaryType = "arraybuffer" ; ws.onopen = (evt ) => { console .log("Connection open ..." ); if (this .offline_callback_arr.length > 0 ) { this .offline_callback_arr.forEach( callback => { console .log('发送离线时的事件' ) callback() }) this .offline_callback_arr = [] } }; ws.onmessage = function (evt ) { if (evt.data instanceof ArrayBuffer ){ let retdata = WebsocketService.parseProtoBufId(evt); let id = retdata.id; let data = retdata.data; self.dealMessage(id,data); }else { console .log("Require array buffer format" ) } }; ws.onclose = function (evt ) { console .log("Connection closed." ); }; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 dealMessage (id: number ,data: Uint8Array ) { switch (id ) { case WebsocketService.ProtocolId.Test: this .dealTest(data) break ; case WebsocketService.ProtocolId.ChatACK: this .dealChatACK(data) break ; default : break ; } } dealChatACK (data: Uint8Array ) { console .log("get ChatACK message!" ); let message = msg.ChatACK.decode(data); console .log(message); }
效果