游戏RPC及抓包简介
Posted 不安分的小QA
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了游戏RPC及抓包简介相关的知识,希望对你有一定的参考价值。
游戏RPC及抓包简介
最近程序在优化代码段过大的问题,其中有个单子的内容是:在FINAL_BUILD下,客户端不应该生成GM RPC相关的东西。其做法是修改RPC框架中自动生成代码的机制,去除最终包体中不需要的RPC代码,达到减少最终包代码段的目的。正好最近看了一点gRPC(一个google开源的rpc框架)的皮毛+wireshark工具。于是想着何不利用wireshark抓个游戏包,看看相关的RPC过程呢。本文就是简单记录下这个过程。
首先介绍两个概念:
抓包即将网络传输发送与接收的数据包进行截获、重发、编辑、转存等操作,也用来检查网络安全。抓包也经常被用来进行数据截取等。平时我们用的抓包工具,主要有2个,wireshark和Fiddler,一般处理HTTP,HTTPS 用Fiddler, 其他协议比如TCP,UDP 就用wireshark。客户端游戏一般基于TCP协议,所以 这里采用wireshark工具演示。这里我先用wireshark抓一个简单的http包展示下wireshark的基本界面:
由于http协议是明文传输,所以可以看到最后的的一串明文信息。,同时大家也可以看到上下文中一些tcp协议,这些就是我们常说的建立连接的三次握手相关的包,这里就不展开说了。
RPC即Remote Procedure Call,翻译过来为“远程过程调用”。目前,主流的平台中都支持各种远程调用技术,以满足分布式系统架构中不同的系统之间的远程通信和相互调用。以游戏用到的RPC举个例子:客户端向服务器发送一个请求A,这个请求A的内容是Function(argv1),即客户端请求在服务器端执行函数Function,并且这个函数的参数是argv1。这个过程就可以简单的理解的RPC。
那我们再深入一些,客户端怎么把参数值传给远程的函数呢?在本地调用中,我们只需要把参数压到栈里,然后让函数自己去栈里读就行。但是在远程过程调用时,客户端跟服务端是不同的进程,不能通过内存来传递参数。这时候就需要客户端把参数先转成一个字节流,传给服务端后,再把字节流转成自己能读取的格式。这个转化过程就叫做序列化。反序列化就是从字节流中解析出参数。概括来说就是:网络传输的数据必须是二进制数据,但调用方请求的出入参数都是对象。对象是不能直接在网络中传输的,所以我们需要提前把它转成可传输的二进制,并且要求转换算法是可逆的,这个过程我们一般叫做“序列化”。这时,服务提供方就可以正确地从二进制数据中分割出不同的请求,同时根据请求类型和序列化类型,把二进制的消息体逆向还原成请求对象,这个过程我们称之为“反序列化”。
序列化好后,就需要传输了。大部分 RPC 框架都使用 TCP 协议,但其实 UDP 也可以, HTTP也可以。为什么大部分使用TCP呢?因为 TCP 协议处于协议栈的下层,能够更加灵活地对协议字段进行定制,减少网络开销,提高性能,实现更大的吞吐量和并发数。HTTP 协议是上层协议,发送包含同等内容的信息,使用 HTTP 协议传输所占用的字节数会比使用 TCP 协议传输所占用的字节数更高。因此在同等网络下,通过 HTTP 协议传输相同内容,效率会比基于 TCP 协议的数据效率要低,信息传输所占用的时间也会更长。
这里不讨论与序列化匹配的加密操作,一般游戏为了安全考虑,都会对RPC进行加密,防止外挂人员通过抓取数据包进行游戏破解。加密不是本文的重点,所以就不展开谈了。(因为我也不懂,哈哈哈哈)
假设你已经在电脑上安装了wireshark客户端,下面我们试着用wireshark对游戏抓包试试。首先是选择目标网卡,同时在最下方的协议过滤一栏中写入tcp,因为我们的目标都是tcp包,这样做可以减少其他类型的包体干扰。
然后根据游戏链接的服务器的ip进行过滤一下,我这里选择的是一台自己私有linux服务器:
选择服务器进入游戏,可以看到客户端与服务器建立TCP连接的过程:
接下来进入游戏后,正常情况下客户端和服务端会进行心跳的同步,例如下图中的1858号报文从客户端向服务器发出了ping,服务端在1860号报文对该数据进行了确认,并且在1861号报文返回了相关信息,客户端在1862号报文进行了确认,这就是一次完整的客户端向服务端的心跳同步流程:
实际过程中,由于网络波动等等原因,可能出现一些tcp数据重传的现象,这个时候一方判断上一条发出的数据超时了,就会尝试重新发送,如下图,wireshark界面中,自动加灰的这些,就是重传的包。
就浅尝辄止介绍到这里吧,毕竟也没打算深究,了解下整个流程而已。
以上是关于游戏RPC及抓包简介的主要内容,如果未能解决你的问题,请参考以下文章