none
socket BeginSend 数据发送到缓冲区问题 RRS feed

  • 问题

  •  MSDN解释:

    在回调方法中,调用 IAsyncResult 参数的 AsyncState 方法可以获取发送 Socket。在获取 Socket 之后,则可以调用 EndSend 方法以成功完成发送操作,并返回发送的字节数。

    如果您使用的是无连接协议,则 EndSend 将一直阻止到发送完数据报为止。如果您使用的是面向连接的协议,则 EndSend 将一直阻塞到发送某缓冲区为止。如果 EndSend 的返回值指示未完全发送该缓冲区,请再次调用 BeginSend 方法,修改该缓冲区以保存未发送的数据。

    不能保证您发送的数据将会立即出现在网络上。为提高网络效率,基础系统可能会延迟传输,直到收集了足够多的传出数据后才开始发送。BeginSend 方法的成功完成意味着基础系统有空间来缓冲用于网络发送的数据。

    注意:

    发送成功完成并不表示数据已成功传递。如果传输系统内没有缓冲区空间可容纳要传输的数据,则发送过程将被阻止,除非套接字已置于非阻止模式。

    -----------------------------------------------------------

    如果 EndSend 的返回值指示未完全发送该缓冲区,请再次调用 BeginSend 方法,修改该缓冲区以保存未发送的数据。

    这个地方怎么再次调用BeginSend 发送,数据已经到缓冲区了,应该系统会自动发送的吧?

    还有上次未解决的问题,数据都到缓冲区了,没法知道接收端到底成功接收多少?在网络不好的情况下,靠缓存区来发送数据也很不稳定,数据经常发不动了。

    问:如何判断缓冲取数据是否发送完成,设置缓冲区大小。如未成功发送,我这可以阻止下一步发送,保证已成功传递。

    使用stream.flush() 也不行。


    不以物喜,不以己悲
    2011年1月6日 2:15

答案

  • Socket.BeginSend本身只保证底层缓冲了要发送的数据.

    如果你选择了TCP协议,你Send到tcp协议栈的数据, tcp协议栈保证对方收到(极端特殊的情况例外);因此,选择了TCP协议方式的Socket的Send成功了,认为发送成功了.

    如果你选择了UDP协议,那Send成功了,只能代表缓冲了

    如果你的数据完整性非常非常重要,可以尝试在应用层即你自己的应用程序上增加自己的协议来处理.

    • 已标记为答案 jieon 2011年1月10日 16:04
    2011年1月10日 8:22

全部回复

  • 去看看英文版的MSDN,上面已经删除了令你抓狂的那一行字

    2011年1月6日 2:47
  • 测试结果,确实给写缓冲区了,如果网络不稳定,一段时间后缓冲区数据就发送不出去了。
    不以物喜,不以己悲
    2011年1月6日 3:51
  • 根据英文解释,可以这样设置 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 0) 意思是0延时发送吧? 英文看不大懂
    不以物喜,不以己悲
    2011年1月6日 5:01
  • 这样还有个问题,就是网络断开了,endsend还是返回成功了,就是数据实际还是写到缓冲区了,求解。


    不以物喜,不以己悲
    2011年1月9日 7:05
  • Socket.BeginSend本身只保证底层缓冲了要发送的数据.

    如果你选择了TCP协议,你Send到tcp协议栈的数据, tcp协议栈保证对方收到(极端特殊的情况例外);因此,选择了TCP协议方式的Socket的Send成功了,认为发送成功了.

    如果你选择了UDP协议,那Send成功了,只能代表缓冲了

    如果你的数据完整性非常非常重要,可以尝试在应用层即你自己的应用程序上增加自己的协议来处理.

    • 已标记为答案 jieon 2011年1月10日 16:04
    2011年1月10日 8:22