凡是以特殊符号开头或结尾来处理粘包的办法,都会有这样那样的缺陷,最终是给自己挖坑。所以,tcp粘包,绝大部分解决方案,偏向于指定数据包长度。这其中大部分使用4字节长度,长度+数据。对方收到的时候,根据长度判断后面数据足够了没有。
这是粘包的处理代码:
每次判断长度,接收一个或多个包,如果接收不完,留下,存起来。等下一个包到来的时候,拼凑完整。
虽然tcp确保数据不丢,但是难免我们自己失手,弄丢了一点点数据。为了避免祸害后面所有包,就需要进行特殊处理了。
每个数据帧,自己把头部长度和数据体凑一起发送啊,tcp确保顺序。这里我们把超时时间设置为3~5秒,每次凑包,如果发现上次有残留,并且超时了,那么就扔了它,省得祸害后面。
根据以上,粘包的关键解决办法,就是设定数据格式,可以看看我们的SRMP协议,1字节标识,1字节序号,2字节长度
如果客户端发送太频繁,服务端tcp缓冲区阻塞,发送窗口会逐步缩小到0,不再接受客户端数据。
1.5 .NetCore版RPC框架NetCore版RPC框架NewLife.ApiServer。
先看看这个效果
我们看这部分代码,4次调用远程函数,成功获取结果,包括二进制高速调用、返回复杂对象、捕获远程异常,没错,这就是一个RPC。
服务端
有没有发现,这个ApiServer跟前面的NetServer有点像?其实ApiServer内部就有一个NetServer
这么些行代码,就几个地方有价值,一个是注册了两个控制器。你可以直接理解为Mvc的控制器,只不过我们没有路由管理系统,直接手工注册。
第二个是指定编码器为Json,用Json传输参数和返回值。其实内部默认就是Json,可以不用指定
看看我们的控制器,特别像Mvc,只不过这里的Controller没有基类,各个Action返回值不是ActionResult,是的,ApiServer就是一个按照Mvc风格设置的RPC框架
返回复杂对象
做请求预处理,甚至拦截异常
像下面这样写RPC服务,然后把它注册到ApiServer上,客户端就可以在1234端口上请求这些接口服务啦
客户端