111,096
社区成员




服务器端,如果设置了接收超时,到了超时的时候, handler.EndReceive(ar) 是否会返回0数据?会出现那种处理情况??
TCP/IP,那么如果网络极差的情况下,中途的5000+4000会不会中途掉包??如果出现这种情况,又如何处理?这个需要人手处理吗?能保证全部接收完成? send/beginsend的返回值表示发送成功的字节数,这个字节数表示发送到本地socket的发送缓存中成功了,并不代表接收端已经成功收到了。 服务端的recv中断与否取决于你怎么编写接收代码,recv/beginrecv仅仅是从socket接收缓存中提取数据而已,有数据来了就会被取出来,例如,客户端一次send了10000,实际过程分为1000+5000+4000到达服务端,那么服务端的recv/beginrecv会返回三次来接收这10000个字节,而不是一直等着10000各字节全部达到再一次性返回。
send/beginsend的返回值表示发送成功的字节数,这个字节数表示发送到本地socket的发送缓存中成功了,并不代表接收端已经成功收到了。 服务端的recv中断与否取决于你怎么编写接收代码,recv/beginrecv仅仅是从socket接收缓存中提取数据而已,有数据来了就会被取出来,例如,客户端一次send了10000,实际过程分为1000+5000+4000到达服务端,那么服务端的recv/beginrecv会返回三次来接收这10000个字节,而不是一直等着10000各字节全部达到再一次性返回。
[quote=引用 3 楼 falcomavin 的回复:] 如果客户端是调用一次send发出去data,网中途断开,那么这次send失败,下次再发不会卡在中间,需要重新send上次失败的data。你说得对,调用一次send系统可能会自动分包发送,而接收方也可能需要多次recv,但这些都与你的上层逻辑无关,多数情况下都不用你去操心。你只要知道这次send失败需要重发就可以肋。 网关那个更是不用关心了,你可以把它想成透明的,对send,recv之类的没有任何影响。
引用 9 楼 jakwin 的回复: 引用 send/beginsend的返回值表示发送成功的字节数,这个字节数表示发送到本地socket的发送缓存中成功了,并不代表接收端已经成功收到了。 服务端的recv中断与否取决于你怎么编写接收代码,recv/beginrecv仅仅是从socket接收缓存中提取数据而已,有数据来了就会被取出来,例如,客户端一次send了10000,实际过程分为1000+5000+4000到达服务端,那么服务端的recv/beginrecv会返回三次来接收这10000个字节,而不是一直等着10000各字节全部达到再一次性返回。 TCP/IP,那么如果网络极差的情况下,中途的5000+4000会不会中途掉包??如果出现这种情况,又如何处理?这个需要人手处理吗?能保证全部接收完成? tcp会保证它们在网路上的时序安全等问题,网络不好会自动重传,如果网断了,自然连接也断了,那么双方都能感知到。其实你也不用想这么复杂,重点关注接收端,以实际收到的内容为准。
如果客户端是调用一次send发出去data,网中途断开,那么这次send失败,下次再发不会卡在中间,需要重新send上次失败的data。你说得对,调用一次send系统可能会自动分包发送,而接收方也可能需要多次recv,但这些都与你的上层逻辑无关,多数情况下都不用你去操心。你只要知道这次send失败需要重发就可以肋。
网关那个更是不用关心了,你可以把它想成透明的,对send,recv之类的没有任何影响。
client.Send(retDatas);
的时候,跟Receive 毫无关系,此时Receive也还是异步执行。
Receive跟Send完全是并发的两支。例如网关在把 Receive累积获得的第一个消息放到一个byte数组msg之中以后,可以调用ThreadPool.QueueUserWorkItem(h => 判断处理程序并调用程序(msg, client));
它在一个子线程中执行反序列化、反射、命令执行等动作,而提前释放了 I/O 线程。
执行命令的代码,可以直接向 client 写消息。此时跟 receive 完全是并发的,根本不纠结什么。scr.Send(mydatas);
这个 mydatas可以是一个1M大的字节数组(你举得例子实在是太小,不典型)。
此时你在服务器端的接收 buffer设置的大小只有1k字节,你怎么知道就正好是1024次Receive接收完毕?
tcp会对数据拆成许多的数据包,例如把这个mydatas拆成1500个数据包,然后数据包可能分别走不同的路由(例如有的数据从上海中转,有的数据从宁波中转),然后到了目的地机器上之后会按照次序组合起来。这时候你的接收端每一次receive的时候,可能收到1024个字节,也可能是1002个字节,并不保证每一次receive都是1024个字节。但是总之是能保证按照顺序接收到,绝不会乱序。
所以你第二个框里边写的“分10次接收”这太想当然了。相同大小相同内容的东西,它完全可能10次、11次、15次接收到,需要多少次receive操作这是不确定的。
回答你最终的问题:
这仍然是两个不同层面的问题。其一,tcp本身对于每一个包都有自己的校验、重传机制,所以它能保证稳定传输,而不会像 udp 那样狂占网络路由器带宽的同时还不保证对方可以收到。tcp 因为有校验、重传、网络阻塞时自动让出带宽的机制,所以一般认为比 udp 更慢一点、更占带宽一点。其实这完全是看哪一个方面来比较。就好像是高速路也很容易被一帮流氓udp给堵死,相反地窄一些的城市马路可能也会因为司机们都比较文明而保持(虽然绝对速度慢一点)通畅。
另一个层面,网络本来就是时断时通的。你设计的任何应用程序,都要在收发tcp 数据异常时关闭连接。客户端则会重建对服务器的连接。那么任何业务数据,也是一样,都有可能“发送失败”。失败以后的策略就是考验系统设计师的真本事的时候了。例如传文件的功能设计,应该支持断点续传,这样才能研发一个用户体验比较好的传文件系统。那些不具有自动化断点续传业务流程的传文件工具也许在偶尔穿点小文件时还凑合用(甚至感觉是最快的),但是一旦网络不稳定,或者传大文件,或者传大批量文件,就怂了,用户立马就想换工具。