NewLife.Net icon indicating copy to clipboard operation
NewLife.Net copied to clipboard

请问如何保证接收的顺序和发送的顺序是一样的

Open 5653325 opened this issue 6 years ago • 5 comments

`//发送方 var TcpClient = new NetUri($"tcp://{remoteIP}:{remotePort}"); var Netclient = TcpClient.CreateRemote(); Netclient.Add<StandardCodec>();//GitHub上看不到 StandardCodec Netclient.Open(); while (data.Length > offset) { …… var pk = new Packet(sendData); Netclient.SendMessage(pk); }

//接收方 var server = new NetServer { …… } server.Add<StandardCodec>();//GitHub上看不到 StandardCodec server.Received += (x, y) => { …… } server.Start();`

请问如何保证接收的顺序和发送的顺序是一样的?现在是接收的时候,包的顺序不是按照发送的顺序接收的。

5653325 avatar Jun 11 '19 08:06 5653325

基于消息通信,为了提升吞吐率,解包完成后,采用异步线程来执行业务逻辑,这是导致消息包顺序不一致的根本原因。

这个修改是今年初执行,你可以说说你的业务场景,大家一起讨论如何设计才能做得更好。

nnhy avatar Jun 12 '19 13:06 nnhy

基于消息通信,为了提升吞吐率,解包完成后,采用异步线程来执行业务逻辑,这是导致消息包顺序不一致的根本原因。

这个修改是今年初执行,你可以说说你的业务场景,大家一起讨论如何设计才能做得更好。

我的需求其实很简单,就是客户端发送文件(必须用Socket,文件大小可能几十M,但不会特别大),服务端接收。我本来是想在客户端发送的时候,头部写上这次是不是第一次发送,服务端那如果收到第一次发送就创建文件,后面的直接写入就行(假设是顺序接收,另外就是NewLife.Net好像没有一直接收的方法,每次信息到了都会触发一次接收事件。),现在是不能按照顺序到达,我就只有在头部信息里在加入一个偏移量信息,告诉服务器这次是从哪里开始写入,写入多少字节。这样的话,感觉无形中增加了报文的内容,总的数据流量有所增加(每次报文多了不少东西)。其实如果NewLife.Net有那种传统Socket的可以直接一直Receive的方法或者可以给一个参数不用异步,保证报文顺序的话,我觉得适用范围会更大一些,毕竟不用每次都在头部报文上做文章了。 谢谢

5653325 avatar Jun 13 '19 09:06 5653325

1,Tcp是流式传递,但是到了网络层,数据是一帧一帧的汇报给用户程序,所以让你觉得“每次信息到了都会触发一次接收事件”; 2,NewLife.Net默认的NetServer/ISocketClient是应用网络库,直接读写网络不涉及协议,数据先后到达,不存在先后到达的情况; 3,ISocketClient里面有SendMessage方法,那是带有SRMP协议的发送接口,服务端如果发现带有协议,则可能会开多线程来进行处理,从而出现你说的先后到达; 4,结合业务场景,建议方案一,不用SRMP协议,直接网络层操作,先发头部,然后每次发送对方顺序接收; 5,建议方案二,采用SRMP协议,每次都带有头部,告诉服务端这次数据包的偏移位置和大小

最后,一个月内,我们会重新进行异步处理网络数据包的必要性,如果优势不明显,将会取消异步处理,重回同步处理时代。

nnhy avatar Jun 23 '19 06:06 nnhy

感谢。

5653325 avatar Jul 02 '19 06:07 5653325

经过几个月考虑,目前找到了一种比较好的解决办法,把“连接复用”功能,从网络层提升到RPC(ApiServer)层,因为目前只有RPC在使用。

代码如下,可以试用!

https://github.com/NewLifeX/X/commit/530e87f779fbac29a80c1b1d86eba9aebbbb5f24

nnhy avatar Sep 01 '19 15:09 nnhy