pitaya学习实践笔记(2)-如何模拟真实游戏客户端连接到服务器

首先,因为真实的客户端不能做到像pitaya-cli一样通过命令行(connect 127.0.0.1:3250)直接连接到服务器,所以需要我们了解客户端与服务端建立tcp连接的过程以及传输报文结构。

这里我们采用tcp连接工具(网络调试助手)来模拟客户端

1

查看pitaya-cli的源码,找到connect命令调用的函数,根据调用堆栈发现connect函数第一步是执行了sendHandshakeRequest()函数:

改代码直接让main函数调用到这里,发现发送的数据的ASCII码是这个:

\x01\x00\x00z{\"sys\":{\"platform\":\"mac\",\"libVersion\":\"0.3.5-release\",\"clientBuildNumber\":\"20\",\"clientVersion\":\"1.0.0\"},\"user\":{\"age\":30}}"

再根据调用的Encode函数得知,其中\x01=type=1,\x00\x00z=len(data)=122

那么服务端在收到数据后又干了什么呢?

这里我们需要进行源码调试来帮助我们理解。为了方便调试,这里直接将源码的demo(pitaya@v1.1.8\examples\demo\cluster\main.go)作为服务器代码。在整个源码中搜索handshake,找到这个函数:func (h *HandlerService) processPacket(,根据调用堆栈推断这里很有可能是处理客户端发来的handshake数据的地方,打上断点来验证:这里选中并直接F5运行起来服务端与客户端的main.go。服务端收到handshake,并回复客户端(SendHandshakeResponse()函数):

 在整个源码中搜索handshakeResponse,找到这个函数:func (c *Client) handleHandshakeResponse(,并在客户端所在的项目找到它并打上断点。调试得知:客户端收到数据包handshakePacket,其中最重要的是这个Type=1=packet.Handshake表示数据包是handshake类型。

客户端收到handshake:

2

紧接着,客户端又发送Type=2=packet.HandshakeAck的数据包给服务端

(发送的数据的ASCII码是这个:\x02\x00\x00\x00

 服务端收到HandshakeAck:至此,tcp握手完毕,建立连接成功

客户端打印了connected!表示成功连接了

3

然后调试发送实际业务请求的流程:

客户端main函数添加:

logger := log.New(os.Stdout, "", log.LstdFlags)

executeCommand(logger, "connect 127.0.0.1:3250")

executeCommand(logger, "request connector.connector.getsessiondata")

select {}

其中我们请求了前端服务器connector的getsessiondata函数,在服务端找到并打个断点。根据调用堆栈找到客户端发送业务数据的核心函数:func (c *Client) sendMsg(

找到最终发送出去的数据的ASCII码:

"\x04\x00\x00%\x00\x01\"connector.connector.getsessiondata"

绿色部分:1个byte  对应constans.go文件的常量:Handshake= 0x01等  ,4表示是业务数据

蓝色部分:3个byte=0x25=%    对应"\x00\x01\"connector.connector.getsessiondata"这一串数据的长度=37

红色部分:分别对应结构体message.Message的type,id(每次累加1)

底层消息数据结构:

服务端收到业务数据请求(packet.Data=Type=4 表示业务) 

最终到达GetSessionData()函数

总结

建立连接到发送业务过程:

1  客户端发送handlshake,服务端返回handlshake

2  客户端发送handshakeAck,连接成功

3  最后发业务数据

客户端发送数据(ASCII码):

\x01\x00\x00z{\"sys\":{\"platform\":\"mac\",\"libVersion\":\"0.3.5-release\",\"clientBuildNumber\":\"20\",\"clientVersion\":\"1.0.0\"},\"user\":{\"age\":30}}

\x02\x00\x00\x00

\x04\x00\x00%\x00\x01\"connector.connector.getsessiondata

然后我们直接通过网络调试助手来按照顺序发送以上内容来模拟真实客户端发送情况:

1

2

3

客户端发送的结构体格式:

1

type 1 byte

len 3 byte

type HandshakeData struct {

        Platform    string `json:"platform"`

        LibVersion  string `json:"libVersion"`

        BuildNumber string `json:"clientBuildNumber"`

        Version     string `json:"clientVersion"`

        User map[string]interface{} `json:"user,omitempty"`

}

2

type 1 byte

len 3 byte

3

type 1 byte

len 3 byte

type Message struct {

        Type       Type   // message type

        ID         uint   // unique id, zero while notify mode

        Route      string // route for locating service

        Data       []byte // payload

        compressed bool   // is message compressed

        Err        bool   // is an error message

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值