java.net.SocketException:连接重置

我正在尝试从套接字读取以下错误。 我正在做的InputStream readInt() ,我得到这个错误。 仔细阅读文档,这表明连接的客户端部分closures了连接。 在这种情况下,我是服务器。

我有权访问客户端日志文件,并且不closures连接,实际上它的日志文件表明我正在closures连接。 那么有人知道为什么会发生这种情况吗? 还有什么要检查的? 当有地方资源达到阈值时,这是否会出现?


我注意到,我有以下行:

 socket.setSoTimeout(10000); 

就在readInt() 。 有一个原因(长话短说),但只是好奇,有什么情况下,这可能导致指出的错误? 我的服务器运行在我的IDE中,而我恰巧把我的IDE卡在一个断点上,然后我注意到在我的IDE中我自己的日志中出现了完全相同的错误。

无论如何,只要提到它,希望不是一个红色的鲱鱼。 🙁

有几个可能的原因。

  1. 另一端故意重新设置连接,我不会在这里列出。 对于应用软件来说这样做是很less见的,而且通常是不正确的,但商业软件并不是未知数。

  2. 更常见的情况是,写入到连接的另一端已经正常closures。 换句话说,应用程序协议错误。

  3. 当套接字接收缓冲区中有未读数据时,也可以通过closures套接字来引起。

  4. 在Windows中,“软件导致连接中止”与“连接重置”不同,是由从您的端点发送的networking问题引起的。 有关于此的Microsoft知识库文章。

连接重置只是意味着收到一个TCP RST。 当你的同伴接收到无法处理的数据时,就会发生这种情况,这可能有多种原因。

最简单的方法是closures套接字,然后在输出stream上写入更多的数据。 通过closures套接字,你告诉同行你已经完成了交谈,并且可以忘记你的连接。 当你在这个stream上发送更多的数据时,对方用RST拒绝它,让你知道它不在听。

在其他情况下,干预防火墙甚至远程主机本身可能会“忘记”您的TCP连接。 如果您长时间不发送任何数据(2小时是常见超时),或者由于对等体重新启动并丢失了有关活动连接的信息,则可能会发生这种情况。 在这些不存在的连接之一上发送数据也会导致RST。


更新以回应额外资讯:

仔细看看你的处理SocketTimeoutException 。 如果在套接字操作中阻塞configuration的超时,则会引发此exception。 抛出此exception时,套接字本身的状态不会改变,但是如果exception处理程序closures了套接字,然后尝试写入套接字,则会处于连接重置状态。 setSoTimeout()意味着给你一个干净的方式来抛出一个read()操作,否则这个操作可能会永远阻塞,而不会执行诸如closures来自另一个线程的套接字等肮脏的事情。

每当我遇到这样的奇怪问题时,我通常会坐下来使用像WireShark这样的工具,看看来回传递的原始数据。 你可能会惊讶于什么东西被断开连接,而你只有在你尝试阅读时才被通知

尴尬地说出来,但是当我遇到这个问题的时候,在我读完所有的数据之前,我只是closures了连接。 在返回小string的情况下,它可以工作,但这可能是由于整个响应被缓冲了,然后才closures它。

在返回的文本数量较多的情况下,抛出exception,因为更多的缓冲区回来了。

你可能会检查这个疏忽。 记住打开一个URL就像一个文件,一旦完全读取,一定要closures它(释放连接)。

你应该仔细检查完整的痕迹,

我有一个服务器套接字应用程序,并修复了一个java.net.SocketException: Connection reset情况。

在我的情况下,它发生在从一个clientSocket Socket对象读取,因为某些原因closures了它的连接。 (networking丢失,防火墙或应用程序崩溃或打算closures)

实际上,当我从这个Socket对象读取时出现错误时,我正在重新build立连接。

 Socket clientSocket = ServerSocket.accept(); is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); int readed = is.read(); // WHERE ERROR STARTS !!! 

有趣的是for my JAVA Socket如果一个客户端连接到我的ServerSocket并closures它的连接,而不发送任何东西is.read()recursion调用自己。似乎是因为在一个无限的while循环读取这个套接字,你尝试阅读从一个封闭的连接。 如果你使用下面的东西进行读取操作;

 while(true) { Receive(); } 

然后,你会得到一个像下面这样的堆栈跟踪

 java.net.SocketException: Socket is closed at java.net.ServerSocket.accept(ServerSocket.java:494) 

我所做的只是closuresServerSocket并更新我的连接,并等待进一步的传入客户端连接

 String Receive() throws Exception { try { int readed = is.read(); .... }catch(Exception e) { tryReConnect(); logit(); //etc } //... } 

这重新build立我的连接未知的客户端套接字丢失

 private void tryReConnect() { try { ServerSocket.close(); //empty my old lost connection and let it get by garbage col. immediately clientSocket=null; System.gc(); //Wait a new client Socket connection and address this to my local variable clientSocket= ServerSocket.accept(); // Waiting for another Connection System.out.println("Connection established..."); }catch (Exception e) { String message="ReConnect not successful "+e.getMessage(); logit();//etc... } } 

我无法find另一种方式,因为从下面的图像看,你无法理解连接是否丢失或没有try and catch ,因为一切似乎都是正确的。 我得到这个快照,而我得到Connection reset不断。

在这里输入图像描述

我有同样的错误。 我现在find了解决问题的办法。 问题是客户端程序在服务器读取stream之前完成。

我用用Java编写的SOA系统遇到了这个问题。 我在不同的物理机器上同时运行客户机和服务器,并且很长一段时间都工作正常,然后那些令人讨厌的连接重置出现在客户机日志中,并且在服务器日志中没有任何奇怪的事情。 重新启动客户端和服务器都没有解决问题。 最后我们发现服务器端的堆很满,所以我们增加了JVM的可用内存:问题解决了! 请注意,日志中没有OutOfMemoryError:内存很less,没有用尽。

我也有一个Java程序尝试通过SSH在服务器上发送命令的问题。 问题在于机器执行Java代码。 它没有连接到远程服务器的权限。 write()方法没有问题,但read()方法抛出了一个java.net.SocketException:Connection reset。 我解决了将客户端SSH密钥添加到远程服务器已知密钥的问题。