【问题标题】:Winsock send() issue with single byte transmissions单字节传输的 Winsock send() 问题
【发布时间】:2013-10-10 05:35:20
【问题描述】:

我遇到了令人沮丧的 Windows 套接字行为,我找不到任何相关信息,所以我想在这里尝试一下。

我的问题如下:

我有一个用作设备驱动程序的 C++ 应用程序,与连接的串行设备通信 通过串行到 TCP/IP 转换器。 串行协议需要在设备和设备之间传递大量单字节消息 我的软件。我注意到这些小消息在启动后只发送了大约 3 次,之后它们不再实际传输(用wireshark检查)。一直以来,send() 方法一直返回 > 0,表明消息已被复制到它的发送缓冲区。 我正在使用阻塞套接字。

我发现了这个问题,因为当发送缓冲区完全填满时,这个特定的驱动程序最终不得不断开它的连接(select() 在大约 5 小时后因此失败,但是当我减小 SO_SNDBUF 大小时它会更快地发生)。

我检查了一下,发现当我用 2 个字节或更大的消息调用 send 时,传输永远不会失败。

非常感谢任何意见,我不知道如何解决这个问题。

【问题讨论】:

  • 经过进一步的测试后,我要添加以下内容:使用相同的串行 tp IP 转换器,并在串行线路上安装了环回连接器,我再次测试了该问题。使用此设置,即使在发送 1 字节消息时也不会出现任何问题。一个很大的不同是我在wireshark 跟踪中看到的内容。我的实际测试系统,带有串行的第 3 方设备,显示许多零窗口探测消息被发送到端口转换器。环回配置不显示正在使用的任何此类标志。
  • 我发送的第一个字节总是在那些零窗口探测消息中结束。当我发送超过 1 个字节时,会发送第二个包,其中包含有效负载的其余部分。当发送第二条消息时,通信保持活跃。当我只发送 1 个字节的消息,而wireshark 只检测到零窗口探测消息时,通信很快就停止了。如果我知道为什么要发送零窗口探测,我不记得端口转换器报告了任何 0 窗口大小。

标签: c++ sockets tcp


【解决方案1】:

当您应该设置 TCP_NODELAY 以便单独写入而不是合并发送时,这种情况很少见。但我认为你还有另一个问题。你确定你正在阅读所有发回的东西吗?并正确地采取行动?对我来说,这听起来像是一个应用程序协议问题。

【讨论】:

  • 我已经尝试过将 TCP_NODELAY 和 SO_SNDBUF 设置为 0 并使用非阻塞端口。发送时的行为没有区别。我可能会补充一点,当使用 SO_SNDBUF 设置为 0 的非阻塞端口时,发送调用会在前几次调用后导致挂断。
  • 当然可以。我看不出将 SO_SNDBUF 归零的意义,但这正是我期望它的行为方式。在我看来,设备甚至没有从连接中读取数据。
  • 没有错误,没有返回,只是冻结。就读取而言:定期从套接字读取所有接收到的数据(我的代码每 100 毫秒循环调用一次)。到目前为止,我的实验只指出重复的 1 字节发送消息会导致出现问题,但发送调用会不断返回 OK 并添加到缓冲区,而缓冲区永远不会通过网络发送出去。我尝试每隔一段时间就为测试目的穿插较长的消息,但只要前面有多个连续的 1 字节消息,它仍然会失败。
  • 归零 SO_SNDBUF 背后的想法是尽量避免让套接字缓冲我的消息。如果另一端没有读取(它是我们经常使用的 VLINX 串行端口转换器),那么为什么更长消息不会引起问题?
猜你喜欢
  • 1970-01-01
  • 2017-02-13
  • 2013-01-02
  • 1970-01-01
  • 1970-01-01
  • 2015-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多