鉴于此堆栈跟踪片段
原因:java.net.SocketException:软件导致连接中止:java.net.SocketOutputStream.socketWrite0(Native Method)处的套接字写入错误
我试图回答以下问题:
什么代码抛出了这个异常? (JVM?/Tomcat?/我的代码?)是什么导致这个异常被抛出?
关于#1:
Sun 的 JVM 源代码不包含此确切消息,但我认为文本 Software cause connection abort: socket write error 来自 SocketOutputStream
的本机实现:
private native void socketWrite0(FileDescriptor fd, byte[] b, int off,
int len) throws IOException;
关于#2
我的猜测是,这是由于客户端在获得完整响应之前终止连接引起的(例如,发送了一个请求,但在获得完整响应之前,它已关闭/终止/离线)
问题:
上述假设是否正确(#1 和#2)?这是否可以与以下情况区分开来:“由于服务器端的网络错误,无法写入客户端”?还是会呈现相同的错误消息?最重要的是:是否有官方文件(例如来自 Sun)说明上述内容?
我需要证明这个堆栈跟踪是套接字客户端的“故障”,并且服务器无法采取任何措施来避免它。 (除了捕获异常,或使用非 Sun JVM SocketOutputStream,尽管两者都不能真正避免客户端已终止的事实)
OutputStream
发送/写入 (outs.write(audioBytes);
) byte[]
时也遇到了这个异常。当音频播放和播放时,如果用户单击任何其他菜单(发送服务器请求),我在控制台上遇到了同样的错误。那么忽略这个异常是否安全?
当本地网络系统中止连接时,可能会发生此错误,例如当 WinSock 在数据重新传输失败后关闭已建立的连接时(接收器从不确认在数据流套接字上发送的数据)。
请参阅this MSDN article。另见Some information about 'Software caused connection abort'。
当创建或访问 a socket(例如 TCP)出错时,会引发 java.net.SocketException
。这通常是在服务器终止连接(没有正确关闭它)时引起的,因此在获得完整响应之前。在大多数情况下,这可能是由超时问题引起的(例如响应花费了太多时间或服务器因请求而过载),或者客户端发送了 SYN,但它没有收到 ACK(连接终止的确认) .对于超时问题,您可以考虑增加超时值。
Socket Exception 通常带有有关该问题的指定详细消息。
详细消息示例:
软件导致连接中止:recv 失败。该错误表示尝试发送消息并且连接已被您的服务器中止。如果在连接数据库时发生这种情况,这可能与使用不兼容的 Connector/J JDBC 驱动程序有关。可能的解决方案:确保您的 CLASSPATH 中有正确的库/驱动程序。
软件导致连接中止:connect。当连接到遥控器出现问题时,可能会发生这种情况。例如,由于病毒检查器拒绝远程邮件请求。可能的解决方案:检查病毒扫描服务是否阻塞了传出连接请求的端口。
软件导致连接中止:套接字写入错误。可能的解决方案:确保将正确长度的字节写入流。因此,请仔细检查您发送的内容。看到这个线程。
对等方重置连接:套接字写入错误/对等方中止连接:套接字写入错误应用程序未检查服务器端的保持活动连接是否已超时。可能的解决方案:在从连接读取之前确保 HttpClient 不为空。E13222_01
对等方重置连接。连接已被对等方(服务器)终止。
连接重置。由于请求的请求,连接已被客户端终止或连接的服务器端关闭。请参阅:是什么导致我的 java.net.SocketException:连接重置?
HttpClient
是 null
不可能导致 SocketException
。没有将正确的长度写入流也不会。
当工作站/笔记本电脑上的企业防火墙挡道时,我经常看到这种情况,它会终止连接。
例如。我在同一台机器上有一个服务器进程和一个客户端进程。服务器正在侦听所有接口(0.0.0.0),客户端尝试连接到公共/家庭接口(注意不是环回接口 127.0.0.1)。
如果机器的网络断开(例如 wifi 关闭),则连接形成。如果机器连接到公司网络(直接或 vpn),则建立连接。
但是,如果机器连接到公共 wifi(或家庭网络),则防火墙会启动并终止连接。在这种情况下,将客户端连接到环回接口可以正常工作,只是不能连接到主/公共接口。
希望这可以帮助。
为了证明哪个组件失败,我将使用 wireshark 监视 TCP/IP 通信并查看谁在实际关闭端口,超时也可能是相关的。
对于任何使用简单的客户端服务器程序并收到此错误的人来说,这是一个未关闭(或关闭到早期)输入或输出流的问题。
你检查过 Tomcat 源代码和 JVM 源吗?这可能会给你更多帮助。
我认为你的总体思路很好。我希望在您无法连接的情况下出现 ConnectException
。上面看起来很像它是客户端驱动的。
我面临着同样的问题。通常发生这种错误是由于客户端已关闭其连接而服务器仍在尝试在该客户端上写入。因此,请确保您的客户端打开连接,直到服务器完成其输出流。还有一件事,不要忘记关闭输入和输出流。
希望这可以帮助。如果仍然面临问题,请在此处详细介绍您的问题。
尽管将正确的证书导入 cacerts 信任库,但有一个 SSLPoke.bat(SSL 故障排除脚本)窗口脚本收到此错误。
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
这个错误发生在我使用 SoapUI 客户端测试我的肥皂服务时,基本上我试图得到一个非常大的消息(> 500kb)并且 SoapUI 通过超时关闭了连接。
在 SoapUI 上转到:File-->Preferences--Socket Timeout(ms)
...并设置一个较大的值,例如 180000(3 分钟),这不会完美解决您的问题,因为文件实际上很大,但至少您会得到响应。
另一个客户端中的关闭连接
就我而言,错误是:
java.net.SocketException: Software caused connection abort: recv failed
它是在调试访问 H2 数据库的 java 应用程序时在 eclipse 中收到的。错误的根源是我最初使用 SQuirreL 打开数据库以手动检查完整性。我确实使用该标志来启用到同一个数据库的多个连接(即 AUTO_SERVER=TRUE
),所以从 java 连接到数据库没有问题。
该错误出现在一段时间后——这是一个漫长的 Java 进程——我决定关闭 SQuirreL 以释放资源。看起来好像 SQuirreL 是“拥有”数据库服务器实例的人,并且它是通过 SQuirreL 连接关闭的。
重新启动 Java 应用程序并没有再次产生错误。
配置
Windows 7的
日食开普勒
松鼠 3.6
org.h2.Driver 版本 1.4.192
在下面解释的情况下,客户端会抛出这样的异常:
服务器被要求验证客户端证书,但客户端提供了扩展密钥使用不支持客户端身份验证的证书,因此服务器不接受客户端的证书,然后关闭连接。
我的服务器在 2 天内抛出了这个异常,我通过移动断开功能解决了这个问题:
outputStream.close();
inputStream.close();
Client.close();
到列表线程的末尾。如果它会帮助任何人。
就我而言,我开发了客户端和服务器端,但我有一个例外:
原因:错误编组参数;嵌套异常是:java.net.SocketException:软件导致连接中止:套接字写入错误
当客户端和服务器中的类不同时。我不在客户端下载服务器的类(接口),我只是在项目中添加相同的文件。但路径必须完全相同。例如,在服务器项目上,我有 java\rmi\services 包和一些 serviceInterface 和实现,我必须在客户端项目上创建相同的包。例如,如果我通过 java/rmi/server/services 更改它,我会得到上述异常。如果客户端和服务器之间的接口版本不同(即使无意中添加了一个空行......我认为 rmi 会生成一种类的哈希来检查版本......我不知道......如果它可以帮助 ...
在模拟其他 API 调用时,我遇到了与 wireMock 相同的问题。之前我是这样定义服务器的:
WireMockServer wireMockServer = null;
但它应该定义如下:
@Rule
public WireMockRule wireMockRule = new WireMockRule(8089);
NullPointerException
,而不是这个问题。