【发布时间】:2021-02-13 02:16:29
【问题描述】:
我正在使用 Java 设计一个系统,其中许多服务器彼此打开 TCP 连接以发送相对少量的数据(比如小于 5KB)。在正常负载下一切正常。但是当我对系统施加压力时,我的一些协议会抛出异常。异常的原因是当对等体 A 完成写入数据时,它在 OutputStream 上调用 .flush() 并关闭套接字。对等体 B 的操作系统在 B 有机会读完所有数据之前终止连接,导致异常。
我怀疑对系统施加压力会加剧这个问题,因为它减少了 B 的线程从套接字读取数据的可用时间,但我不确定。
我看到了通过让客户端启动套接字关闭来解决此问题的建议。 但是,我不清楚谁是客户。在协议期间,A 和 B 都可以相互发送多条消息。
所以我现在想知道是否有人可以推荐一个简单的规则,即哪一方应该关闭连接,以及如何关闭。根据我阅读的内容,我认为读取协议最后一条消息的一方应该关闭它。关于如何关闭连接,假设对等体 B 收到最后一条消息。所以一个简单的解决方案是让 B 向 A 发送一个字节,然后关闭套接字。 A 等待这个字节,然后关闭套接字。
有什么想法吗?
【问题讨论】:
-
B 出现什么错误?你能发布一些代码吗?当 A 关闭套接字时,B 不应出现异常。它应该仍然能够在到达 EOF 之前读取所有待处理的数据。操作系统会将未读数据存储在缓冲区中;它不会把它扔掉。如果您可以创建一个minimal reproducible example,其中包含演示问题的代码和完整的错误消息,将会很有帮助。
-
上次我运行它时我得到了这个(我知道这是一个写异常,这与我上面描述的不同(它是一个读异常)。但它是同一件事。出于某种原因套接字在另一侧有机会完成写入之前被一侧关闭) java.net.SocketException: Broken pipe java.net.SocketOutputStream.socketWrite0(Native Method) java.net.SocketOutputStream.socketWrite(SocketOutputStream.java: 109) java.net.SocketOutputStream.write(SocketOutputStream.java:141)
-
写异常是可以的。它告诉你对方已经关闭了连接,所以没有必要尝试写任何东西,因为没有人在听。只是不要将其视为致命错误。