我在尝试从套接字读取时遇到以下错误。我正在对该readInt()执行InputStream,并且出现此错误。仔细阅读文档,这表明连接的客户端部分关闭了连接。在这种情况下,我是服务器。

我可以访问客户端日志文件,并且它没有关闭连接,实际上,它的日志文件表明我正在关闭连接。那么,有人知道为什么会这样吗?还有什么要检查的?当存在可能达到阈值的本地资源时,会出现这种情况吗?


我确实注意到我有以下一行:

socket.setSoTimeout(10000);


readInt()之前。这是有原因的(长话短说),但出于好奇,在某些情况下这可能会导致指示的错误?我的服务器在我的IDE中运行,我碰巧使我的IDE卡在一个断点上,然后我发现完全相同的错误开始出现在我自己的IDE日志中。

提起它,希望不是红鲱鱼。 :-(

评论

双方都有堆叠痕迹吗?您能否再描述一下网络架构? (通过野外互联网?在一台计算机上?介于两者之间?)它是否一直存在?还是断断续续的?

参见stackoverflow.com/questions/585599/…

#1 楼

可能有多种原因。

另一端故意重置了连接,在此我不再赘述。对于应用程序软件而言,这样做很少见,而且通常是不正确的,但对于商业软件而言却并非没有。
更常见的是,由于写入连接而导致另一端已经正常关闭。换句话说,是应用程序协议错误。
也可能是由于套接字接收缓冲区中有未读数据而关闭套接字导致的。
在Windows中,“软件导致连接中止”不是与“连接重置”相同,是由您的终端发送的网络问题引起的。有关此的Microsoft知识库文章。


评论


@MattLyons谢谢。有比这更好的MSDN文章。坦白说,我觉得很难相信。建立正确的源IP地址和目标IP地址后,连接甚至不存在。我见过的MSDN文章提到了永久性网络错误,导致连接超时。

–user207421
2012年5月30日上午10:13

#2 楼

连接重置只是意味着已收到TCP RST。当您的对等方收到无法处理的数据时,就会发生这种情况,并且可能有多种原因。
最简单的方法是关闭套接字,然后在输出流上写入更多数据。通过关闭套接字,您就可以告诉对等端您已经完成交谈,并且它可能会忘记您的连接。无论如何,当您在该流上发送更多数据时,对等方都会通过RST拒绝它,以让您知道它没有在监听。

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


更新以响应其他信息:

仔细查看您的处理方法。 SocketTimeoutException。如果在套接字操作上被阻止时超过了配置的超时,则会引发此异常。引发此异常时,套接字本身的状态不会更改,但是如果您的异常处理程序关闭了套接字,然后尝试对其进行写入,则您将处于连接重置状态。 setSoTimeout()旨在为您提供一种干净的方法来突破read()操作,否则该操作可能永远被阻塞,而无需执行诸如从另一个线程关闭套接字的肮脏操作。

评论


在某些方面不正确。垃圾回收和进程退出均会导致正确的关闭,而不是重置,但是在对等之后进行写操作的关闭可能导致重置而不是EOS。仅当读取器设置了读取超时时,才会引发SocketTimeoutExceptions。

–user207421
2012年9月30日0:21在

这并不总是意味着已收到RST。这也可能意味着这一边产生了一个。

–user207421
17年4月14日在17:35

而且,您无法写入已关闭的套接字。您将获得SocketException:套接字关闭,并且对等方将不会获得RST。答案是完全错误的。

–user207421
11月12日6:46



#3 楼

每当遇到类似这样的奇怪问题时,我通常都会使用WireShark之​​类的工具来查看来回传递的原始数据。在断开连接的情况下,您可能会感到惊讶,并且只有在尝试阅读时才会收到通知。

#4 楼

不好意思地说,但是当我遇到这个问题时,我在读取所有数据之前关闭连接只是一个错误。在返回小的字符串的情况下,它可以正常工作,但这可能是由于在我关闭它之前缓冲了整个响应。 ,因为缓冲区又又回来了。

您可以检查一下此疏忽。请记住,打开URL就像一个文件一样,请确保在完全读取它之后将其关闭(释放连接)。

#5 楼

您应该非常仔细地检查完整的跟踪信息,
我有一个服务器套接字应用程序,并修复了java.net.SocketException: Connection reset的情况。
在我的情况下,它发生在读取由于某种原因而关闭其连接的clientSocket Socket对象时。 (网络丢失,防火墙或应用程序崩溃或打算关闭)
实际上,当我从此Socket对象读取错误时,我正在重新建立连接。
Socket clientSocket = ServerSocket.accept();
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
int readed = is.read(); // WHERE ERROR STARTS !!!

有趣的是for my JAVA Socket如果客户端连接到我的ServerSocket并关闭其连接而没有发送任何内容is.read()反复被调用。这似乎是由于处于无限循环中以便从此套接字读取数据,因此您尝试从关闭的连接中读取数据。
如果使用像下面这样的读取操作;
while(true)
{
  Receive();
}

然后您会得到一个堆栈跟踪下面的内容
java.net.SocketException: Socket is closed
    at java.net.ServerSocket.accept(ServerSocket.java:494)

我所做的只是关闭ServerSocket并更新连接并等待进一步的传入客户端连接
String Receive() throws Exception
{
try {                   
            int readed = is.read();
           ....
}catch(Exception e)
{
        tryReConnect();
        logit(); //etc
}


//...
}

这重新建立了我的连接,以防止未知的客户端套接字丢失
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...
            }
        }

我找不到其他方法,因为从下图可以看到,您无法理解如果没有q43120,连接是否丢失79q,因为一切似乎都正确。我连续获取try and catch时得到了此快照。


评论


is.read()不会递归调用自身。

–user207421
11月12日下午6:47

@MarquisofLorne是的,这就是为什么该例程处于另一个while循环中的原因。

– DavutGürbüz
11月12日7:48

@MarquisofLorne在阅读自己的答案后注意到,它需要被“反复调用”。感谢您指出。 5年前:)。实际上,我现在基于读取-1,添加了超时异常等对它进行了改进。不良的连接断开仍然是问题,人们遵循不同的不活动管理方法。

– DavutGürbüz
11月23日22:32

#6 楼

我有同样的错误。我现在找到了解决问题的方法。问题是客户端程序在服务器读取流之前已完成。

评论


那不会单独导致此异常。

–user207421
2012年6月12日21:20

如果System.exit(0)杀死了该程序,并且没有人调用socket.close(),因为连接处于错误状态并且未正确关闭,那么情况就好了。 sooo更正确地说,他有一个不关闭套接字就关闭的客户端程序;)这是一件坏事,应该修复。

–迪恩·希勒(Dean Hiller)
2012年11月9日20:29



@DeanHiller不,不会。操作系统将以与应用程序相同的方式关闭套接字。

–user207421
13-10-5在23:27



@EJP ....我不确定...我只知道我们可以用System.exit复制它,但是我不记得OS / config,因为那是相当早的事情了....调用socket.close( )在服务器上阻止了连接重置,并且行为更加正常。

–迪恩·希勒(Dean Hiller)
13年10月7日在12:14

@DeanHiller在写入过程完成之前,读取过程已退出。

–user207421
14年5月18日在11:57



#7 楼

我用Java编写的SOA系统遇到了这个问题。我在不同的物理计算机上同时运行客户端和服务器,并且它们可以正常工作很长时间,然后那些讨厌的连接重置出现在客户端日志中,并且服务器日志中没有任何奇怪的地方。重新启动客户端和服务器都无法解决问题。最终,我们发现服务器端的堆已满,因此我们增加了JVM可用的内存:问题解决了!请注意,日志中没有OutOfMemoryError:内存只是稀缺,没有耗尽。

#8 楼

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

#9 楼

检查服务器的Java版本。发生这种情况是因为我的Weblogic 10.3.6是在TLSv1上的JDK 1.7.0_75上。我尝试使用的其余端点关闭了低于TLSv1.2的任何内容。

默认情况下,Weblogic试图协商最强的共享协议。在此处查看详细信息:设置HTTPS连接的https.protocols系统属性的问题。

我添加了详细的SSL日志记录以标识受支持的TLS。这表明TLSv1正在用于握手。 -Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

我通过将功能推出到我们的JDK8兼容产品中来解决了此问题,JDK8默认为TLSv1.2。对于限于JDK7的用户,我还通过升级到TLSv1.2成功地测试了Java 7的变通方法。我用了这个答案:如何在Java 7中启用TLS 1.2

评论


非常感谢,您告诉我解决问题的新方向。最后我发现情况确实如此!!!

–卡尔李
6月1日7:39



SSL协议不匹配不会导致连接重置。它们会导致握手失败。

–user207421
11月12日下午6:48

#10 楼

以我的经验,我经常遇到以下情况;


如果您在公司工作,请与网络和安全团队联系。因为在对外部服务的请求中,可能需要授予相关端点的权限。
另一个问题是,运行您的应用程序的服务器上的SSL证书可能已过期。


评论


SSL证书不会导致连接重置。

–user207421
11月12日下午6:49