关闭 TCP 协议的简单规则

时间:2021-02-13 02:16:29

标签: java sockets tcp

我正在使用 Java 设计一个系统,其中许多服务器彼此打开 TCP 连接以发送相对少量的数据(比如小于 5KB)。在正常负载下一切正常。但是当我对系统施加压力时,我的一些协议会抛出异常。出现异常的原因是,当一个peer A写完数据后,它调用了OutputStream上的.flush()并关闭了socket。对端 B 的操作系统在 B 有机会读取完所有数据之前终止连接,导致异常。

我怀疑系统压力会加剧这个问题,因为它减少了 B 的线程从套接字读取数据的可用时间,但我不确定。

我看到了通过让客户端启动套接字关闭来解决此问题的建议。 但是,我不清楚谁是客户。在协议过程中,A 和 B 都可以互相发送多条消息。

所以我现在想知道是否有人可以为哪一方应该关闭连接以及如何关闭连接推荐一个简单的规则。根据我的阅读,我认为阅读协议最后一条消息的一方应该关闭它。关于如何关闭连接,假设对等方 B 收到最后一条消息。所以一个简单的解决方案是让 B 向 A 发送一个字节,然后关闭套接字。 A 等待这个字节,然后关闭套接字。

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

阅读更多内容后,似乎当套接字关闭时,会交换 FIN ACK 消息。我认为它被称为优雅关闭(而不是强制关闭)。这些消息并不是真正的消息,而只是数据包中的标志;数据包还可能携带对等方正在写入的数据。接收到数据后,即使设置了这些标志,也将其存储在接收缓冲区中。关键是即使在套接字关闭后也可以从缓冲区中读取数据。但是,套接字关闭后无法写入套接字。如果我错了,请纠正我。

所以,A 写 B 是可以的,让 A 关闭 A 端的套接字,让 B 读取,然后让 B 关闭 B 端的套接字。

关于我的问题中描述的问题,我发现实际发生的事情是这样的: A 发起与 B 的协议。 B 正在做的前期工作耗时太长,并且受到超时的保护。因为这段代码在套接字的 try-with-resources 子句中,当超时发生时,线程首先被中断,然后套接字被关闭。 B 的代码位于包装类中,用于检查协议执行期间是否发生异常。如果是,则向 A 写入错误代码。但由于套接字已关闭,因此写入操作失败。 A 同时不知道超时并开始向 B 写入数据。所以 A 也得到了异常

答案 1 :(得分:-2)

有一种方法 Socket.shutdownInput() 允许一侧关闭一个方向。另一端会得到EOF,然后可以关闭socket。