异常: 连接重置

尝试从套接字读取时出现以下错误。我正在对那个 InputStreamreadInt(),我得到了这个错误。仔细阅读文档,这表明连接的客户端部分关闭了连接。在这个场景中,我是服务器。

我可以访问客户端日志文件,但它没有关闭连接,事实上它的日志文件表明我正在关闭连接。有人知道为什么会这样吗?还要检查什么?是否在当地资源可能达到临界值的情况下出现这种情况?


我注意到我有以下几句话:

socket.setSoTimeout(10000);

就在 readInt()之前。这是有原因的(说来话长) ,但只是好奇,是否有情况下,这可能导致指示的错误?我让服务器在 IDE 中运行,然后碰巧让 IDE 停留在一个断点上,然后我注意到同样的错误开始出现在 IDE 中我自己的日志中。

不管怎样,只是提一下,希望不是转移话题

1039440 次浏览

每当我遇到这样奇怪的问题时,我通常会使用像 网络鲨鱼这样的工具来查看来回传递的原始数据。你可能会感到惊讶的东西正在断开,你只是作为 通知当你尝试和阅读。

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

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

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


根据补充资料更新:

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

有几种可能的原因。

  1. 另一端故意重置了连接,我不会在这里记录。对于应用程序软件来说,这样做是罕见的,而且通常是不正确的,但是对于商业软件来说,这并不是不可知的。

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

  3. 当套接字接收缓冲区中存在未读数据时,关闭套接字也可能导致这种情况。

  4. 在 Windows 中,“软件导致连接中止”与“连接重置”不同,是由于从您的终端发送的网络问题造成的。有一篇关于这方面的微软知识库文章。

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

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

在返回的文本数量较长的情况下,将引发异常,因为返回的缓冲区数量超过了这个数量。

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

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

我在使用 Java 编写的 SOA 系统中遇到了这个问题。我在不同的物理机器上运行客户端和服务器,它们工作了很长一段时间,然后那些讨厌的连接重置出现在客户端日志中,服务器日志中没有任何奇怪的东西。重新启动客户端和服务器并没有解决问题。最后,我们发现服务器端的堆相当满,因此我们增加了 JVM 的可用内存: 问题解决了!请注意,日志中没有 OutOfMemory 错误: 内存是稀缺的,而不是耗尽的。

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

我有一个服务器套接字应用程序和固定的 java.net.SocketException: Connection reset情况下。

在我的例子中,它发生在从 clientSocketSocket对象读取时,由于某种原因,该对象关闭了其连接。(网络丢失、防火墙或应用程序崩溃或意图关闭)

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

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

有趣的是,如果一个客户端连接到我的 ServerSocket并关闭它的连接而没有发送任何信息,那么 for my JAVA Socket就会被重复调用。这似乎是因为在一个无限的 while 循环中从这个套接字读取信息,而你试图从一个关闭的连接中读取信息。 如果您使用下面这样的方式进行读操作;

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

我找不到其他的方法,因为正如你从下面的图片中看到的,你不能理解没有 try and catch连接是否会丢失,因为一切看起来都是正确的。我得到这个快照时,我正在获得 Connection reset连续。

enter image description here

检查服务器的 Java 版本。发生在我身上是因为我的 Weblogic10.3.6在 JDK1.7.0 _ 75上,而 JDK1.7.0 _ 75在 TLSv1上。我尝试使用的其余端点是关闭 TLSv1.2以下的所有端点。

默认情况下,Weblogic 试图协商最强的共享协议。

我添加了详细的 SSL 日志记录来识别支持的 TLS。
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

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

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

  1. 如果您在一家公司工作,请与网络和安全团队联系。因为在向外部服务提出的请求中,可能需要向 对相关端点给予许可。请求

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

我的情况是 DNS problem
我把 host file的解决 IP 和一切工作正常。 当然这不是一个永久的解决方案把这给我时间来修复 DNS 的问题。

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

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

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

在我的情况下,这是与 TSL 版本的问题。我在 OkHttp 客户端上使用卢克菲特,在服务器端更新 ALB 后,我应该删除我的配置与 ConnectionSpecs:

OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
List<ConnectionSpec> connectionSpecs = new ArrayList<>();
connectionSpecs.add(ConnectionSpec.COMPATIBLE_TLS);
//      clientBuilder.connectionSpecs(connectionSpecs);

因此,尝试删除或添加此配置以使用不同的 TSL 配置。

我过去常常使用‘ NotifyUtil: : java.net。SocketException: 在 java.net 上重置连接。在 Netbeans7.4设置的 Apache 控制台中的 SocketInputStream.read (SocketInputStream.java: ...’消息。

我尝试了很多解决方案来摆脱它,对我有效的是在 Tomcat 上启用 TLS。

以下是如何:

创建密钥存储库文件来存储服务器的私钥和 通过执行以下命令自签名证书:

视窗:

“% JAVA _ HOME% bin keytool”-genkey-alias tomcat-keyalg RSA

Unix:

$JAVA _ HOME/bin/keytool-genkey-alias tomcat-keyalg RSA

并指定一个密码值“ changeit”。

根据 href = “ https://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html”rel = “ nofollow norefrer”> https://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html (这将在 localuser 目录中创建一个. keystore 文件)

然后编辑 server.xml (取消注释并编辑相关行)文件(% CATALINA _ HOME% apache-tomcat-7.0.41.0 _ base conf server.xml)以启用 SSL 和 TLS 协议:

 <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" keystorePass="changeit" />

希望这个能帮上忙