“软件导致连接中止: 套接字写入错误”的正式原因

给定这个堆栈跟踪片段

引自: java.net. SocketException: 软件导致连接中止: 套接字写入错误 < br > at SocketOutputStream.socketWrite0(原生 方法)

我试图回答以下问题:

  1. 抛出这个异常的代码是什么? (JVM?/Tomcat?/我的代码?)
  2. 引发此异常的原因是什么?

关于 # 1:

Sun 的 JVM 源代码没有包含这个确切的消息,但是我认为文本 软件导致连接中止: 套接字写入错误来自于 SocketOutputStream的本地实现:

private native void socketWrite0(FileDescriptor fd, byte[] b, int off,
int len) throws IOException;

关于 # 2

我的猜测是,当客户端在获得完整响应之前终止了连接(例如,发送了一个请求,但是在获得完整响应之前,它被关闭/终止/离线) ,就会导致这种情况

问题:

  1. 上述假设是否正确(1号和2号) ?
  2. 这与“由于 服务器端的网络错误而无法写入客户端”的情况有什么不同吗?或者会呈现相同的错误消息?
  3. 最重要的是: 是否有正式文件(例如来自太阳的文件)说明上述情况?

我需要证明这个堆栈跟踪是套接字客户机的“错误”,并且服务器无法避免这个错误。(除了捕获异常,或者使用非 Sun JVM SocketOutputStream,尽管两者都不能真正避免客户端终止的事实)

387081 次浏览

您检查过 Tomcat 源代码 还有和 JVM 源代码吗? 这可能会给您更多的帮助。

我认为你的总体思路是好的。我希望在你无法连接的情况下有一个 ConnectException。上面看起来非常像是客户驱动的。

为了证明哪个组件出现故障,我将使用 电鲨监视 TCP/IP 通信,并观察谁实际上正在关闭端口,也可能与超时有关。

当本地网络系统中止 连接,例如当 WinSock 关闭已建立的连接时 数据重传失败后(接收方从不确认已发送的数据 在数据流套接字上)。

参见 这篇 MSDN 的文章,也参见 关于“软件导致连接中止”的一些信息

我经常看到这种情况,当工作站/笔记本电脑上的公司防火墙阻碍连接时,它会切断连接。

例如。我在同一台机器上有一个服务器进程和一个客户端进程。服务器正在监听所有接口(0.0.0.0) ,客户机尝试连接到 public/home 接口(注意,不是回送接口127.0.0.1)。

如果机器的网络被切断(如无线网络关闭) ,那么连接就形成了。如果机器连接到公司网络(直接或 vpn) ,则形成连接。

但是,如果机器连接到公共 wifi (或家庭网络) ,那么防火墙会切断连接。在这种情况下,将客户机连接到环回接口可以正常工作,只是不能连接到主/公共接口。

希望这个能帮上忙。

对于任何使用简单 ClientServer 程序并得到此错误的人来说,这是一个未关闭(或关闭到早期)输入或输出流的问题。

我的服务器在过去的两天里抛出了这个异常,我通过移动断开函数解决了这个问题:

outputStream.close();
inputStream.close();
Client.close();

到列表线程的末尾。 如果这对任何人都有帮助的话。

我也面临着同样的问题。
通常,这种错误发生的原因是客户端已经关闭了它的连接,而服务器仍然试图在该客户端上写入。
因此,请确保客户端的连接在服务器完成其输出流之前一直处于打开状态。
还有一件事,不要忘记关闭输入和输出流。

希望这个能帮上忙。
如果仍然面临的问题,比简要介绍你的问题在这里的细节。

当创建或访问 一个插座(如 TCP)时出现错误,将引发 java.net.SocketException。这通常是由于服务器已经终止了连接(没有正确关闭它) ,所以在获得完整响应之前造成的。在大多数情况下,这可能是由超时问题(例如响应时间太长或服务器因请求而超载)或客户机发送了 SYN,但没有收到 ACK (连接终止的确认)。对于超时问题,可以考虑增加超时值。

Socket Exception 通常带有关于该问题的指定详细信息。

详细信息的例子:

  • 软件导致连接中止: recv 失败。

    错误指示尝试发送邮件,并且服务器已中止连接。如果这是在连接到数据库时发生的,则可能与使用 不兼容的连接器/J JDBC 驱动程序有关。

    可能的解决方案: 确保在 CLASSPATH 中有适当的库/驱动程序。

  • 软件导致连接中止: 连接。

    这可能发生在连接到远程的问题上,例如 由于病毒检查器拒绝远程邮件请求

    可能的解决方案: 检查病毒扫描服务是否阻塞了连接发出请求的端口。

  • 软件导致连接中止: 套接字写入错误。

    可能的解决方案: 确保向流写入的字节长度正确。所以仔细检查一下你发的是什么。看这个 线

  • 通过对等点重置连接: 套接字写错误/通过对等点中止连接: 套接字写错误

    应用程序没有检查服务器端的 keep-alive 连接是否超时。

    可能的解决方案: 在从连接读取之前确保 HttpClient 是非空的。 < sup > < a href = “ https://docs.oracle.com/cd/E13222 _ 01/wls/docs61/note/bugfixes2.html”rel = “ norefrer”> E13222 _ 01

  • 通过对等点重置连接。

    连接已被对等(服务器)终止。

  • 连接重置。

    由于对请求的请求,连接或者被客户端终止,或者被连接的服务器端关闭。

    是什么导致了我的 java.net。 SocketException: 连接重置?

这个错误发生在我使用 SoapUI 客户端测试肥皂服务时,基本上我试图得到一个非常大的消息(> 500kb) ,而 SoapUI 通过超时关闭了连接。

在 SoapUI 上转到:

文件-> 首选项-Socket 超时(ms)

... 并把一个大的值,如180000(3分钟) ,这将不是完美的修复你的问题,因为文件实际上是大,但至少你会有一个响应。

我在调试其他 API 调用时也遇到了与 wireMock 相同的问题。 之前我是这样定义服务器的:

WireMockServer wireMockServer = null;

但它的定义应如下所示:

@Rule
public WireMockRule wireMockRule = new WireMockRule(8089);

另一个客户端中的闭合连接

在我的例子中,错误是:

java.net.SocketException: Software caused connection abort: recv failed

它是在 Eclipse 调试访问 H2数据库的 Java 应用程序时接收到的。错误的来源是我最初用 SQuirL 打开数据库以手动检查完整性。我确实使用了该标志来启用到同一数据库的多个连接(即 AUTO_SERVER=TRUE) ,所以从 java 连接到数据库没有问题。

过了一段时间之后——这是一个漫长的 Java 进程——我决定关闭 SQuirrel 以释放资源时,出现了这个错误。似乎 SQuirL 是“拥有”数据库服务器实例的那个,并且它已经通过 SQurelL 连接关闭了。

重新启动 Java 应用程序不会再次产生错误。

配置

  • 视窗7
  • Eclipse Kepler 月食开普勒
  • 松鼠3.6
  • Org.h2驱动程序版本1.4.192

在下面解释的情况下,客户端将抛出这样一个异常:

服务器被要求对客户端证书进行身份验证,但是客户端提供了一个扩展密钥使用不支持客户端身份验证的证书,因此服务器不接受客户端的证书,然后关闭连接。

在我的案例中,我开发了客户端和服务器端,但有一个例外:

原因: 错误编组参数; 嵌套异常是: 例外: 软件导致连接中止: 套接字 写入错误

当客户端和服务器中的类不同时。我不在客户端下载服务器类(接口) ,我只是在项目中添加相同的文件。 但路线必须完全一样。 例如,在服务器项目中,我有 java rmi 服务包和一些 serviceInterface 和实现,我必须在客户端项目中创建相同的包。例如,如果我通过 java/rmi/server/services 修改它,就会得到上面的异常。 同样的例外,如果接口版本是不同的客户端和服务器之间(即使添加了一个空行不经意... 我认为 rmi 使一种类散列检查版本... 我不知道..。 如果能帮上忙的话..。

有一个 SSLPoke.bat (SSL 故障排除脚本)窗口脚本,尽管将正确的证书导入到 ccerts 信任库中,但该脚本仍然得到了这个错误。

C:\Java\jdk1.8.0_111\jre\lib\security>SSLPoke.bat


C:\Java\jdk1.8.0_111\jre\lib\security>"C:\jdk1.8.0_101\jre\bin\java"
`SSLPoke  tfs.corp.****.com  443`


java.net.SocketException: Software caused connection abort: recv failed
`at java.net.SocketInputStream.socketRead0(Native Method)`
`at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)`
`at java.net.SocketInputStream.read(SocketInputStream.java:170)`
`at java.net.SocketInputStream.read(SocketInputStream.java:141)`
`at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)`
`at sun.security.ssl.InputRecord.read(InputRecord.java:503)`
`at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)`
`at sun.security.ssl.SSLSocketImpl.performInitialHandshake
(SSLSocketImpl.java:1375)`
`at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)`
`at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)`
`at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:138)`
`at SSLPoke.main(SSLPoke.java:28)`

然后我检查了一些关于我工作中网络变化的旧笔记 在某些情况下需要添加 JVM 参数 -Djava.net.preferIPv4Stack=true to make connections to certain machines 在我们的网络,以避免这个错误。

C:\Java\jdk1.8.0_111\jre\lib\security>"C:\Java\jdk1.8.0_111\bin\java"  
**-Djava.net.preferIPv4Stack=true**  SSLPoke tfs.corp.****.com 443

成功连接

可在此下载 SSLPoke 的代码: Https://gist.github.com/4ndrej/4547029