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=到tcpdump(1)
和/或snoop(1M)
看看两边的电线上发生了什么。考虑到您描述的“魔法”,这可能是寻找解释的最佳选择。找到它们后发布更多详细信息。
【讨论】:
从我的虚拟客户端的连接到它停止的部分,这就是 snoop 产生的:【参考方案2】:只有当它没有收到对已发送内容的 TCP 确认时,您才会得到超时。您的转储显示所有发送的数据都已确认,因此不应该没有超时。发送的唯一数据是来自 solaris61 的 2 个字节。
听起来您是在说您打算向 solaris61 发送一些数据。该数据从未发送过。你如何发送这些数据?如果您使用缓冲 stdio 进行写入,则数据可能仍在缓冲区中。例如,如果它是行缓冲的,那么它将被缓冲,直到发送换行符。相反,您可以使用setvbuf()
关闭缓冲,或者只使用send()
直接发送数据。
(如果您已经这样做了,请发布该部分代码。)
【讨论】:
但是话说回来,它不是最多只能在缓冲区中停留几秒钟吗?实际上,我曾尝试让它静置几个小时,但没有任何反应。我可以尝试使用 send 和 recv,但问题是我在遗留系统上这样做。所以会有很多地方需要改变。尽管如此,我会尝试使用 setvbuf 的建议。 您正在考虑内核中的 TCP 缓冲区。这些缓冲区将自动发送出去,但不会发送 stdio 缓冲区。 我明白你的意思。但我一直在将我正在使用的版本与一个更旧的版本进行比较。而且旧版本运行良好。这就是使用假人的地方。如果这是问题所在,那么我不能只使用类似于 fflush() 的东西吗? 如果您实际上使用的是 stdio,那么fflush()
也可以。
好吧,这里有一点需要澄清。问题是 write() 调用没有返回。有了这个,就不可能调用其他任何东西。所以我认为未填充的缓冲区是问题所在。以上是关于TCP Socket 不接收数据,写入/发送不超时?的主要内容,如果未能解决你的问题,请参考以下文章