TCP Socket 不接收数据,写入/发送不超时?

Posted

技术标签:

【中文标题】TCP Socket 不接收数据,写入/发送不超时?【英文标题】:TCP Socket not receiving data, write/send does not timeout? 【发布时间】:2010-11-24 16:19:11 【问题描述】:

我已经使用 TCP 套接字制作了几个项目和模型,但这是我第一次遇到这种情况。

我在 solaris sparc 机器上有一个 Linux 服务器应用程序,它应该接受来自 Web 服务器上的 OCX 的连接,但没有收到数据。我使用 netstat 来验证连接是否已建立。

我创建了一个小型 tcp 客户端来连接以充当 Web 服务器/ocx,但发生的事情是在写入时它停止在那里并且永远不会发生超时。即使我离开连接并等待几个小时,也没有任何反应。我什至使用 setsockopt 来确保设置低超时值。此外,在另一端,没有接收到数据,并且 select 语句在轮询 fd 集时超时。

有没有人知道为什么 write 或 send 在写入 sokcet 时不会超时?另外,有谁知道为什么服务器上没有设置read fd set?

这里是 snoop 的转储:

solaris61 -> 10.1.0.37    TCP D=8882 S=35111 Fin Ack=1805515051 Seq=897643511 Len=0 Win=49640
10.1.0.37 -> solaris61    TCP D=35111 S=8882 Ack=897643512 Seq=1805515051 Len=0 Win=24818
solaris61 -> 10.1.0.37    TCP D=8882 S=35112 Syn Seq=921698308 Len=0 Win=49640 Options=<mss 1460,nop,wscale 0,nop,nop,sackOK>
10.1.0.37 -> solaris61    TCP D=35112 S=8882 Syn Ack=921698309 Seq=1829645518 Len=0 Win=24820 Options=<nop,wscale 0,nop,nop,sackOK,mss 1460>
solaris61 -> 10.1.0.37    TCP D=8882 S=35112 Ack=1829645519 Seq=921698309 Len=0 Win=49640
solaris61 -> 10.1.0.37    TCP D=8882 S=35112 Push Ack=1829645519 Seq=921698309 Len=2 Win=49640
10.1.0.37 -> solaris61    TCP D=35112 S=8882 Ack=921698311 Seq=1829645519 Len=0 Win=24818

使用“snoop -x0 -s1500”

solaris61 -> 10.1.0.37 TCP D=8882 S=35291 Syn Seq=4205016629 Len=0 Win=49640 Options=

   0: 0800 20f5 a3b5 000c 295d 6f44 0800 4500    .. .....)]oD..E.
  16: 0034 e4c7 4000 4006 0000 0a01 003d 0a01    .4..@.@......=..
  32: 0025 89db 22b2 faa3 7635 0000 0000 8002    .%.."...v5......
  48: c1e8 148a 0000 0204 05b4 0103 0300 0101    .è..............
  64: 0402                                       ..

10.1.0.37 -> solaris61 TCP D=35291 S=8882 Syn Ack=4205016630 Seq=799808987 Len=0 Win=24820 Options=

   0: 000c 295d 6f44 0800 20f5 a3b5 0800 4500    ..)]oD.. .....E.
  16: 0034 c849 4000 4006 5e17 0a01 0025 0a01    .4.I@.@.^....%..
  32: 003d 22b2 89db 2fac 1ddb faa3 7636 8012    .=".../.....v6..
  48: 60f4 8ec1 0000 0103 0300 0101 0402 0204    `...............
  64: 05b4                                       ..

solaris61 -> 10.1.0.37 TCP D=8882 S=35291 Ack=799808988 Seq=4205016630 Len=0 Win=49640

   0: 0800 20f5 a3b5 000c 295d 6f44 0800 4500    .. .....)]oD..E.
  16: 0028 e4c8 4000 4006 0000 0a01 003d 0a01    .(..@.@......=..
  32: 0025 89db 22b2 faa3 7636 2fac 1ddc 5010    .%.."...v6/...P.
  48: c1e8 147e 0000                             .è.~..

solaris61 -> 10.1.0.37 TCP D=8882 S=35291 Push Ack=799808988 Seq=4205016630 Len=2 Win=49640

   0: 0800 20f5 a3b5 000c 295d 6f44 0800 4500    .. .....)]oD..E.
  16: 002a e4c9 4000 4006 0000 0a01 003d 0a01    .*..@.@......=..
  32: 0025 89db 22b2 faa3 7636 2fac 1ddc 5018    .%.."...v6/...P.
  48: c1e8 1480 0000 750a                        .è....u.

10.1.0.37 -> solaris61 TCP D=35291 S=8882 Ack=4205016632 Seq=799808988 Len=0 Win=24818

   0: 000c 295d 6f44 0800 20f5 a3b5 0800 4500    ..)]oD.. .....E.
  16: 0028 c84a 4000 4006 5e22 0a01 0025 0a01    .(.J@.@.^"...%..
  32: 003d 22b2 89db 2fac 1ddc faa3 7638 5010    .=".../.....v8P.
  48: 60f2 cf8c 0000 5555 5555 5555              `.....UUUUUU

solaris61 -> 10.1.0.37 TCP D=8882 S=35291 Fin Ack=799808988 Seq=4205016632 Len=0 Win=49640

   0: 0800 20f5 a3b5 000c 295d 6f44 0800 4500    .. .....)]oD..E.
  16: 0028 e4ca 4000 4006 0000 0a01 003d 0a01    .(..@.@......=..
  32: 0025 89db 22b2 faa3 7638 2fac 1ddc 5011    .%.."...v8/...P.
  48: c1e8 147e 0000                             .è.~..

10.1.0.37 -> solaris61 TCP D=35291 S=8882 Ack=4205016633 Seq=799808988 Len=0 Win=24818

   0: 000c 295d 6f44 0800 20f5 a3b5 0800 4500    ..)]oD.. .....E.
  16: 0028 c84b 4000 4006 5e21 0a01 0025 0a01    .(.K@.@.^!...%..
  32: 003d 22b2 89db 2fac 1ddc faa3 7639 5010    .=".../.....v9P.
  48: 60f2 cf8b 0000 5555 5555 5555              `.....UUUUUU

【问题讨论】:

solaris61 -> 10.1.0.37 TCP D=8882 S=35111 Fin Ack=1805515051 Seq=897643511 Len=0 Win=49640 10.1.0.37 -> solaris61 TCP D=35111 S=8882 Ack=897643512 Seq=1805515051 Len=0 Win=24818 solaris61 -> 10.1.0.37 TCP D=8882 S=35112 Syn Seq=921698308 Len=0 Win=49640 Options= 10.1 .0.37 -> solaris61 TCP D=35112 S=8882 Syn Ack=921698309 Seq=1829645518 Len=0 Win=24820 Options= solaris61 -> 10.1.0.37 TCP D =8882 S=35112 Ack=1829645519 Seq=921698309 Len=0 Win=49640 solaris61 -> 10.1.0.37 TCP D=8882 S=35112 Push Ack=1829645519 Seq=921698309 Len=2 Win=49640 10.1.0.37 -> solaris61 TCP D=35112 S=8882 Ack=921698311 seq=1829645519 Len=0 Win=24818 @marcus,您可以编辑问题本身,那里的可读性会更高。 @Nikolai,我真傻,我没有先编辑就直接从终端复制了它。 握手没问题,solaris61 向 10.1.0.37 发送 2 个字节,TCP 堆栈已确认。你能检查发送的内容吗(即使用“-o 文件名”和“-s 1500”选项窥探文件) 【参考方案1】:

tcpdump(1) 和/或snoop(1M) 看看两边的电线上发生了什么。考虑到您描述的“魔法”,这可能是寻找解释的最佳选择。找到它们后发布更多详细信息。

【讨论】:

从我的虚拟客户端的连接到它停止的部分,这就是 snoop 产生的:【参考方案2】:

只有当它没有收到对已发送内容的 TCP 确认时,您才会得到超时。您的转储显示所有发送的数据都已确认,因此不应该没有超时。发送的唯一数据是来自 solaris61 的 2 个字节。

听起来您是在说您打算向 solaris61 发送一些数据。该数据从未发送过。你如何发送这些数据?如果您使用缓冲 stdio 进行写入,则数据可能仍在缓冲区中。例如,如果它是行缓冲的,那么它将被缓冲,直到发送换行符。相反,您可以使用setvbuf() 关闭缓冲,或者只使用send() 直接发送数据。

(如果您已经这样做了,请发布该部分代码。)

【讨论】:

但是话说回来,它不是最多只能在缓冲区中停留几秒钟吗?实际上,我曾尝试让它静置几个小时,但没有任何反应。我可以尝试使用 send 和 recv,但问题是我在遗留系统上这样做。所以会有很多地方需要改变。尽管如此,我会尝试使用 setvbuf 的建议。 您正在考虑内核中的 TCP 缓冲区。这些缓冲区将自动发送出去,但不会发送 stdio 缓冲区。 我明白你的意思。但我一直在将我正在使用的版本与一个更旧的版本进行比较。而且旧版本运行良好。这就是使用假人的地方。如果这是问题所在,那么我不能只使用类似于 fflush() 的东西吗? 如果您实际上使用的是 stdio,那么 fflush() 也可以。 好吧,这里有一点需要澄清。问题是 write() 调用没有返回。有了这个,就不可能调用其他任何东西。所以我认为未填充的缓冲区是问题所在。

以上是关于TCP Socket 不接收数据,写入/发送不超时?的主要内容,如果未能解决你的问题,请参考以下文章

.NET下使用Socket进行TCP传输时数据发送或接收不全

socket缓冲区以及阻塞模式

如何设置socket的Connect超时

TCP/UDP socket

为啥我的socket接收大数据的时候接收不完全

用socket发送接收数据,但每次接收的数据字节长度都大于发送的25个字节?