java.net.SocketException:连接重置

时间:2008-09-15 13:36:43

标签: java sockets networking connection socketexception

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

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


我注意到我有以下一行:

socket.setSoTimeout(10000);

就在readInt()之前。这是一个原因(长篇故事),但只是好奇,是否存在可能导致指示错误的情况?我在我的IDE中运行了服务器,我碰巧让我的IDE卡在断点上,然后我注意到完全相同的错误开始出现在我自己的IDE中。

无论如何,只要提一下,希望不是红鲱鱼。 : - (

12 个答案:

答案 0 :(得分:100)

有几种可能的原因。

  1. 另一端故意重置连接,我不会在这里记录。应用软件执行此操作很少见且通常不正确,但商业软件并不为人所知。

  2. 更常见的是,它是通过写入另一端已正常关闭的连接引起的。换句话说,应用程序协议错误。

  3. 当套接字接收缓冲区中有未读数据时,也可能因关闭套接字而引起。

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

答案 1 :(得分:41)

连接重置只是意味着收到了TCP RST。当您的对等方收到无法处理的数据时会发生这种情况,并且可能有多种原因。

最简单的是关闭套接字,然后在输出流上写入更多数据。通过关闭套接字,你告诉你的同伴你已经完成了谈话,它可以忘记你的连接。无论如何,当您在该流上发送更多数据时,对等方会使用RST拒绝它,以告知您它没有正在侦听。

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


更新以回应其他信息:

仔细查看您对SocketTimeoutException的处理。如果在套接字操作上阻止超出配置的超时,则会引发此异常。抛出此异常时,套接字本身的状态不会更改,但如果您的异常处理程序关闭套接字,然后尝试写入它,则您将处于连接重置状态。 setSoTimeout()旨在为您提供一种简洁的方法来打破read()操作,否则可能会永远阻塞,而不会像从另一个线程关闭套接字那样做坏事。

答案 2 :(得分:13)

每当我遇到像这样的奇怪问题时,我通常会坐下来使用像WireShark这样的工具,然后查看来回传递的原始数据。您可能会对事情断开连接感到惊讶,并且当您尝试阅读时,您只是通知

答案 3 :(得分:8)

令人尴尬地说出来,但是当我遇到这个问题时,我在阅读所有数据之前关闭连接只是一个错误。在返回小字符串的情况下,它可以工作,但这可能是由于整个响应在我关闭之前被缓冲了。

如果返回的文本数量较长,则抛出异常,因为缓冲区的数量会超过。

您可以检查这种疏忽。请记住,打开一个URL就像一个文件,一旦完全阅读,请务必将其关闭(释放连接)。

答案 4 :(得分:7)

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

我是一个服务器套接字应用程序并修复了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循环中从这个套接字读取,你试图从一个封闭的连接读取。 如果您使用类似下面的内容进行读取操作;

while(true)
{
  Receive();
}

然后你会得到一个类似下面的stackTrace

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...
            }
        }

我无法找到另一种方式,因为从下图中可以看出,如果没有try and catch,您无法理解连接是否丢失,因为一切似乎都是正确的。我连续Connection reset时得到了这张快照。

enter image description here

答案 5 :(得分:5)

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

答案 6 :(得分:4)

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

答案 7 :(得分:1)

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

答案 8 :(得分:1)

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

默认情况下,Weblogic试图协商最强的共享协议。在此处查看详细信息:Issues with setting https.protocols System Property for HTTPS connections

我添加了详细的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的变通方法。我用了这个答案:How to enable TLS 1.2 in Java 7

答案 9 :(得分:0)

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

  1. 如果您在公司工作,请与网络和安全团队联系。因为在对外部服务的请求中,可能有必要授予相关端点的权限。

  2. 另一个问题是,运行应用程序的服务器上的 SSL证书可能已过期

答案 10 :(得分:0)

就我而言是 DNS problem .
我输入了 host file 解析的 IP,一切正常。 当然这不是一个永久的解决方案,这让我有时间解决 DNS 问题。

答案 11 :(得分:0)

我见过这个问题。就我而言,在特定 Java 类中重用相同的 ClientRequest 对象会导致错误。该项目使用的是 Jboss Resteasy

  1. 最初只有一种方法是使用/调用对象 ClientRequest(作为类中的全局变量放置)在特定 URL 中执行请求。
  2. 之后,创建了另一种方法来使用另一个 URL 获取数据,但重用了相同的 ClientRequest 对象。

解决方案:在同一个类中创建了另一个 ClientRequest 对象,并且不能重复使用。