Socat未关闭TCP连接。

5

我使用 socat 1.7.3.1-r0 并在一个 alpine 3.3 的 Linux 服务器上运行以下命令:

socat -d -d -d PTY,link=/dev/ttyFOOBAR,echo=0,raw,unlink-close=0 TCP-LISTEN:7000,forever,reuseaddr

Socat会监听客户端,并通过TCP将虚拟串口/dev/ttyFOOBAR的数据传递给客户端,同时接收客户端的数据并传递回虚拟串口。当客户端断开连接后,socat应该退出。

当连接建立时,socat将记录以下内容:

I socat by Gerhard Rieger - see www.dest-unreach.org
I This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)
I This product includes software written by Tim Hudson (tjh@cryptsoft.com)
I setting option "symbolic-link" to "/dev/ttyFOOBAR"
I setting option "echo" to 0
I setting option "raw"
I setting option "unlink-close" to 0
I openpty({5}, {6}, {"/dev/pts/3"},,) -> 0
N PTY is /dev/pts/3
I setting option "forever" to 1
I setting option "so-reuseaddr" to 1
I socket(2, 1, 6) -> 7
I starting accept loop
N listening on AF=2 0.0.0.0:7000
I accept(7, {2, AF=2 CLIENT_IP:PORT}, 16) -> 8
N accepting connection from AF=2 CLIENT_IP:PORT on AF=2 172.20.0.2:7000
I permitting connection from AF=2 CLIENT_IP:PORT
I close(7)
I resolved and opened all sock addresses
N starting data transfer loop with FDs [5,5] and [8,8]

服务器上的ss命令会输出以下内容:

Netid  State      Recv-Q Send-Q Local Address:Port                 Peer Address:Port                
tcp    ESTAB      0      0      172.20.0.2:7000                 CLIENT_IP:PORT

问题是,当我断开客户端(关闭它)时,TCP连接仍然建立,并且没有来自socat的附加日志。 ss仍显示连接为ESTAB。有什么想法吗?当我再次连接客户端时,以下内容出现在日志中:
W read(8, 0x7fa8f48c4020, 8192): Connection reset by peer
N socket 2 to socket 1 is in error
N socket 2 (fd 8) is at EOF
I poll timed out (no data within 0.500000 seconds)
I close(5)
I shutdown(8, 2)
I shutdown(8, 2): Socket not connected
N exiting with status 0

但为什么这会在连接时发生而不是断开连接时发生呢?

socat 正在使用端口 5000。ss 在端口 7000 上报告了其他内容。 - user207421
@EJP 只是一个打字错误。已经修复了。 - DarkLeafyGreen
你的意思是这个输出不是从源代码中复制粘贴出来的吗?这样做并不能增强信心。 - user207421
无论如何,这个问题都不是主题。请尝试访问http://superuser.com。 - user207421
@EJP 这是复制和粘贴的。我只改了 IP 和端口,使它匿名化。 - DarkLeafyGreen
你没有使用TCP保持连接,因此服务器不知道客户端已经离开,直到它再次尝试向客户端发送数据。 - lossleader
1个回答

11

如果套接字上没有要发送或接收的数据,并且您断开了底层连接,则双方都不知道,直到尝试发送数据。通常,这将是应用程序级别的数据,但在协议级别上,您可以启用TCP keep alives来模拟流动数据,无论何时没有真实数据。

根据socat手册的说法,您可以尝试类似以下命令:

socat -d -d -d PTY,link=/dev/ttyFOOBAR,echo=0,raw,unlink-close=0 TCP-LISTEN:7000,forever,reuseaddr,keepalive,keepidle=10,keepintvl=10,keepcnt=2

(keepalive 确实看起来是必要的选项,但如果未设置调整选项的默认值仍不清楚。)

(keepalive 实际上看起来是一个重要选项,但如果没有设定调整选项的默认值仍然不太清楚.)


通常情况下,当默认值未被全局或应用程序(如此处的socat)在Linux上更改时,探测间隔默认为2小时。 - A.B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接