关于socket中途断网或网络问题

jakwin 2016-06-22 09:48:09


请问?socket的运作是如何的,如何保证全部接收或中途作废?
...全文
2954 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
黑娃 2016-06-24
  • 打赏
  • 举报
回复
如果是因为网络时延巨大导致这种情况,同时在一段时间内tcp没有断开却不能正常通信,你就需要用心跳机制来主动检查网络,如果心跳失败,则可以先于tcp的断开机制,提交判定是网络不好问题,进而主动断开,重新开始逻辑。
黑娃 2016-06-24
  • 打赏
  • 举报
回复
引用 14 楼 jakwin 的回复:
引用
引用 9 楼 jakwin 的回复: 引用 send/beginsend的返回值表示发送成功的字节数,这个字节数表示发送到本地socket的发送缓存中成功了,并不代表接收端已经成功收到了。 服务端的recv中断与否取决于你怎么编写接收代码,recv/beginrecv仅仅是从socket接收缓存中提取数据而已,有数据来了就会被取出来,例如,客户端一次send了10000,实际过程分为1000+5000+4000到达服务端,那么服务端的recv/beginrecv会返回三次来接收这10000个字节,而不是一直等着10000各字节全部达到再一次性返回。 TCP/IP,那么如果网络极差的情况下,中途的5000+4000会不会中途掉包??如果出现这种情况,又如何处理?这个需要人手处理吗?能保证全部接收完成? tcp会保证它们在网路上的时序安全等问题,网络不好会自动重传,如果网断了,自然连接也断了,那么双方都能感知到。其实你也不用想这么复杂,重点关注接收端,以实际收到的内容为准。
又有其他问题出现,TCP/IP服务器端长时间收不到后半部分的数据,如何通知服务器端不要再接收后端数据?再通知客户端再重新发送一次完整新数据过来或者通知客户端接收数据失败先操作其他内容!
为什么会长时间收不到后面的数据呢?tcp没有断开?
jakwin 2016-06-24
  • 打赏
  • 举报
回复
恩,对的,结贴!
黑娃 2016-06-23
  • 打赏
  • 举报
回复
引用 11 楼 jakwin 的回复:
服务器端,如果设置了接收超时,到了超时的时候, handler.EndReceive(ar) 是否会返回0数据?会出现那种处理情况??
socket的timeout属性只针对同步方式,异步是没有超时设定的,如果对方没有任何数据过来,beginrecive注册的回掉是不会执行的
jakwin 2016-06-23
  • 打赏
  • 举报
回复
服务器端,如果设置了接收超时,到了超时的时候, handler.EndReceive(ar) 是否会返回0数据?会出现那种处理情况??
黑娃 2016-06-23
  • 打赏
  • 举报
回复
引用 9 楼 jakwin 的回复:
引用
send/beginsend的返回值表示发送成功的字节数,这个字节数表示发送到本地socket的发送缓存中成功了,并不代表接收端已经成功收到了。 服务端的recv中断与否取决于你怎么编写接收代码,recv/beginrecv仅仅是从socket接收缓存中提取数据而已,有数据来了就会被取出来,例如,客户端一次send了10000,实际过程分为1000+5000+4000到达服务端,那么服务端的recv/beginrecv会返回三次来接收这10000个字节,而不是一直等着10000各字节全部达到再一次性返回。
TCP/IP,那么如果网络极差的情况下,中途的5000+4000会不会中途掉包??如果出现这种情况,又如何处理?这个需要人手处理吗?能保证全部接收完成?
tcp会保证它们在网路上的时序安全等问题,网络不好会自动重传,如果网断了,自然连接也断了,那么双方都能感知到。其实你也不用想这么复杂,重点关注接收端,以实际收到的内容为准。
jakwin 2016-06-23
  • 打赏
  • 举报
回复
引用
send/beginsend的返回值表示发送成功的字节数,这个字节数表示发送到本地socket的发送缓存中成功了,并不代表接收端已经成功收到了。 服务端的recv中断与否取决于你怎么编写接收代码,recv/beginrecv仅仅是从socket接收缓存中提取数据而已,有数据来了就会被取出来,例如,客户端一次send了10000,实际过程分为1000+5000+4000到达服务端,那么服务端的recv/beginrecv会返回三次来接收这10000个字节,而不是一直等着10000各字节全部达到再一次性返回。
TCP/IP,那么如果网络极差的情况下,中途的5000+4000会不会中途掉包??如果出现这种情况,又如何处理?这个需要人手处理吗?能保证全部接收完成?
黑娃 2016-06-23
  • 打赏
  • 举报
回复
引用 4 楼 jakwin 的回复:
[quote=引用 3 楼 falcomavin 的回复:] 如果客户端是调用一次send发出去data,网中途断开,那么这次send失败,下次再发不会卡在中间,需要重新send上次失败的data。你说得对,调用一次send系统可能会自动分包发送,而接收方也可能需要多次recv,但这些都与你的上层逻辑无关,多数情况下都不用你去操心。你只要知道这次send失败需要重发就可以肋。 网关那个更是不用关心了,你可以把它想成透明的,对send,recv之类的没有任何影响。
例如:如果从中国发生数据到美国,即是如果中国客户端用BeginSend一次性send出去后返回成功的字节就表明已经成功发生到美国的服务器吧?上层应用的服务器端只要能调用到BeginReceive就表示能全部接收到数据是吗?上层应用的服务器端分多次接收中途不会中断的是吧(如果客户端send成功)? [/quote] send/beginsend的返回值表示发送成功的字节数,这个字节数表示发送到本地socket的发送缓存中成功了,并不代表接收端已经成功收到了。 服务端的recv中断与否取决于你怎么编写接收代码,recv/beginrecv仅仅是从socket接收缓存中提取数据而已,有数据来了就会被取出来,例如,客户端一次send了10000,实际过程分为1000+5000+4000到达服务端,那么服务端的recv/beginrecv会返回三次来接收这10000个字节,而不是一直等着10000各字节全部达到再一次性返回。
jakwin 2016-06-23
  • 打赏
  • 举报
回复
引用
引用 9 楼 jakwin 的回复: 引用 send/beginsend的返回值表示发送成功的字节数,这个字节数表示发送到本地socket的发送缓存中成功了,并不代表接收端已经成功收到了。 服务端的recv中断与否取决于你怎么编写接收代码,recv/beginrecv仅仅是从socket接收缓存中提取数据而已,有数据来了就会被取出来,例如,客户端一次send了10000,实际过程分为1000+5000+4000到达服务端,那么服务端的recv/beginrecv会返回三次来接收这10000个字节,而不是一直等着10000各字节全部达到再一次性返回。 TCP/IP,那么如果网络极差的情况下,中途的5000+4000会不会中途掉包??如果出现这种情况,又如何处理?这个需要人手处理吗?能保证全部接收完成? tcp会保证它们在网路上的时序安全等问题,网络不好会自动重传,如果网断了,自然连接也断了,那么双方都能感知到。其实你也不用想这么复杂,重点关注接收端,以实际收到的内容为准。
又有其他问题出现,TCP/IP服务器端长时间收不到后半部分的数据,如何通知服务器端不要再接收后端数据?再通知客户端再重新发送一次完整新数据过来或者通知客户端接收数据失败先操作其他内容!
xuzuning 2016-06-23
  • 打赏
  • 举报
回复
socket 封装了 TCP/IP,使得我们在使用时不需要考虑 TCP/IP 通讯的细节 在传输途中如果遇到致命的错误(如断网、数据包总是校验错...)socket 会给你一个错误提示(异常),这是你需要顾及的 socket 毕竟只是一个工具,他不可能预知你的业务是否完成。因此你还是需要适当的干预通讯的过程,至少是在数据到来时,你得将数据保存起来,并清空缓冲区。直到你完整的接收到数据 如果客户端是分块发送数据的(有点断点续传的意思),你就得及时告知客户端:接收到了那几块,还有那几块没有收到(或有问题)
jakwin 2016-06-23
  • 打赏
  • 举报
回复


c#的socket是否这样理解?
jakwin 2016-06-23
  • 打赏
  • 举报
回复
服务器端的StateObject.BufferSize的大小我限制为1024,客户端发送1GB的数据到服务器端,当客户端BeginSend返回成功的数据,就表明服务器端已经全部接收完成呢?服务器端开始分多少次数接收的时候,是否已经全部数据都在服务器端了呢?
jakwin 2016-06-23
  • 打赏
  • 举报
回复
引用 3 楼 falcomavin 的回复:
如果客户端是调用一次send发出去data,网中途断开,那么这次send失败,下次再发不会卡在中间,需要重新send上次失败的data。你说得对,调用一次send系统可能会自动分包发送,而接收方也可能需要多次recv,但这些都与你的上层逻辑无关,多数情况下都不用你去操心。你只要知道这次send失败需要重发就可以肋。
网关那个更是不用关心了,你可以把它想成透明的,对send,recv之类的没有任何影响。


例如:如果从中国发生数据到美国,即是如果中国客户端用BeginSend一次性send出去后返回成功的字节就表明已经成功发生到美国的服务器吧?上层应用的服务器端只要能调用到BeginReceive就表示能全部接收到数据是吗?上层应用的服务器端分多次接收中途不会中断的是吧(如果客户端send成功)?
黑娃 2016-06-23
  • 打赏
  • 举报
回复
如果客户端是调用一次send发出去data,网中途断开,那么这次send失败,下次再发不会卡在中间,需要重新send上次失败的data。你说得对,调用一次send系统可能会自动分包发送,而接收方也可能需要多次recv,但这些都与你的上层逻辑无关,多数情况下都不用你去操心。你只要知道这次send失败需要重发就可以肋。 网关那个更是不用关心了,你可以把它想成透明的,对send,recv之类的没有任何影响。
zhishiheng 2016-06-23
  • 打赏
  • 举报
回复
自定义那个协议 接受完之后再组包
  • 打赏
  • 举报
回复
另外,你第三个框中,什么叫做“服务器分10次就收完数据,主机才分10次接收数据”?(应用系统的,而非底层通讯系统的)网关就是接收、发送完整的消息的。当网关接收到完整的一个 mydatas消息,例如分1520次Receive操作,其中最后一次接收的数据不但有 mydatas 的结尾信息,还有客户端发来的下一个消息的开头信息。网关解析出这个mydatas消息,判断用哪一个过程来处理它,然后调用这个过程。 网关不断地接受数据,这个Receive跟Send 完全是异步、无关的!当你要通过网关
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 数据异常时关闭连接。客户端则会重建对服务器的连接。那么任何业务数据,也是一样,都有可能“发送失败”。失败以后的策略就是考验系统设计师的真本事的时候了。例如传文件的功能设计,应该支持断点续传,这样才能研发一个用户体验比较好的传文件系统。那些不具有自动化断点续传业务流程的传文件工具也许在偶尔穿点小文件时还凑合用(甚至感觉是最快的),但是一旦网络不稳定,或者传大文件,或者传大批量文件,就怂了,用户立马就想换工具。

111,096

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧