[英]java.net.SocketException: Connection reset
我在尝试从套接字读取时收到以下错误。 我正在对该InputStream
执行readInt()
,并且收到此错误。 仔细阅读文档,这表明连接的客户端部分关闭了连接。 在这种情况下,我是服务器。
我可以访问客户端日志文件并且它没有关闭连接,实际上它的日志文件表明我正在关闭连接。 那么有人知道为什么会这样吗? 还有什么要检查的? 当当地资源可能达到阈值时,是否会出现这种情况?
我确实注意到我有以下行:
socket.setSoTimeout(10000);
就在readInt()
之前。 这是有原因的(长篇故事),但只是好奇,是否存在可能导致指示错误的情况? 我的服务器在我的 IDE 中运行,我碰巧让我的 IDE 卡在断点上,然后我注意到完全相同的错误开始出现在我自己的 Z581D6381F3F35E4F9ACD4Z772018B36 的日志中
无论如何,只是提一下,希望不是红鲱鱼。 :-(
有几个可能的原因。
另一端故意重置连接,我不会在这里记录。 应用软件很少这样做,而且通常是不正确的,但对于商业软件来说并不陌生。
更常见的情况是,写入连接的另一端已经正常关闭。 换句话说,应用程序协议错误。
当套接字接收缓冲区中有未读数据时关闭套接字也可能导致此问题。
在 Windows 中,“软件导致连接中止”与“连接重置”不同,是由您端发送的网络问题引起的。 有一篇关于此的 Microsoft 知识库文章。
连接重置仅仅意味着收到了 TCP RST。 当您的对等方接收到它无法处理的数据时,就会发生这种情况,这可能有多种原因。
最简单的就是当你关闭socket,然后在output stream上写入更多数据。 通过关闭套接字,您告诉您的对等方您已完成通话,它可以忘记您的连接。 无论如何,当您在该 stream 上发送更多数据时,对等方会使用 RST 拒绝它,让您知道它没有在听。
在其他情况下,干预防火墙甚至远程主机本身可能会“忘记”您的 TCP 连接。 如果您长时间不发送任何数据(2 小时是常见的超时),或者因为对等方重新启动并丢失了有关活动连接的信息,则可能会发生这种情况。 在这些失效连接之一上发送数据也会导致 RST。
更新以响应其他信息:
仔细查看您对SocketTimeoutException
的处理。 如果在套接字操作上阻塞时超过了配置的超时,则会引发此异常。 抛出此异常时,套接字本身的 state 不会更改,但如果您的异常处理程序关闭套接字,然后尝试写入它,您将处于连接重置状态。 setSoTimeout()
旨在为您提供一种干净的方法来摆脱可能会永远阻塞的read()
操作,而无需执行诸如从另一个线程关闭套接字之类的肮脏事情。
每当我遇到类似这样的奇怪问题时,我通常会使用WireShark之类的工具坐下来查看来回传递的原始数据。 您可能会对断开连接的地方感到惊讶,并且只有在您尝试阅读时才会收到通知。
你应该非常仔细地检查完整的痕迹,
我有一个服务器套接字应用程序并修复了java.net.SocketException: Connection reset
case。
在我的情况下,它发生在从 clientSocket Socket
object 读取时,由于某种原因关闭了它的连接。 (网络丢失、防火墙或应用程序崩溃或有意关闭)
实际上,当我从这个 Socket object 读取时出错时,我正在重新建立连接。
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();
}
然后你会得到一个类似下面的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
时得到了这个快照。
说起来很尴尬,但是当我遇到这个问题时,我在读取所有数据之前关闭连接简直是一个错误。 在返回小字符串的情况下,它可以工作,但这可能是因为在我关闭它之前整个响应都被缓冲了。
在返回大量文本的情况下,将引发异常,因为返回的缓冲区更多。
你可能会检查这个疏忽。 请记住打开 URL 就像一个文件,一旦完全读取,请务必关闭它(释放连接)。
我有同样的错误。 我现在找到了问题的解决方案。 问题是客户端程序在服务器读取流之前完成。
我在使用 Java 编写的 SOA 系统时遇到了这个问题。 我在不同的物理机器上同时运行客户端和服务器,它们工作了很长时间,然后那些讨厌的连接重置出现在客户端日志中,服务器日志中没有任何奇怪的东西。 重新启动客户端和服务器并没有解决问题。 最后我们发现服务器端的堆比较满了,所以我们增加了JVM可用的memory:问题解决:注意日志中没有OutOfMemoryError,ZCD69B4957F06CD818D7BF3D61。 没有筋疲力尽。
检查您的服务器的 Java 版本。 发生在我身上是因为我的 Weblogic 10.3.6 在 TLSv1 上的 JDK 1.7.0_75 上。 我试图使用的 rest 端点正在关闭 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 的解决方法。 我使用了这个答案: How to enable TLS 1.2 in Java 7
我也遇到了 Java 程序试图通过 SSH 在服务器上发送命令的问题。 问题在于执行 Java 代码的机器。 它没有连接到远程服务器的权限。 write() 方法运行良好,但 read() 方法抛出 java.net.SocketException: Connection reset。 我通过将客户端 SSH 密钥添加到远程服务器已知密钥来解决此问题。
在我的情况下是DNS problem
。
我将已解析的 IP 放入host file
中,一切正常。 当然,这不是一个永久的解决方案,这让我有时间解决 DNS 问题。
根据我的经验,我经常会遇到以下情况;
如果您在公司公司工作,请联系网络和安全团队。 因为在向外部服务发出的请求中,可能需要授予相关端点的权限。
另一个问题是SSL 证书在您的应用程序运行的服务器上可能已过期。
我已经看到了这个问题。 就我而言,在特定的 Java class 中重用相同的 ClientRequest object 会导致错误。 该项目使用Jboss Resteasy 。
解决方案:在同一个 class 中创建了另一个 ClientRequest object 并且专门不被重用。
就我而言,这是 TSL 版本的问题。 我将 Retrofit 与 OkHttp 客户端一起使用,在服务器端更新 ALB 后,我应该使用connectionSpecs删除我的配置:
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
List<ConnectionSpec> connectionSpecs = new ArrayList<>();
connectionSpecs.add(ConnectionSpec.COMPATIBLE_TLS);
// clientBuilder.connectionSpecs(connectionSpecs);
因此,请尝试删除或添加此配置以使用不同的 TSL 配置。
我曾经在我的 Netbeans7.4 设置的 Apache 控制台中收到“NotifyUtil::java.net.SocketException: Connection reset at java.net.SocketInputStream.read(SocketInputStream.java:...”消息。
我尝试了许多解决方案来摆脱它,对我有用的是在 Tomcat 上启用 TLS。
以下是如何:
通过执行以下命令创建一个密钥库文件来存储服务器的私钥和自签名证书:
Windows:
"%JAVA_HOME%\bin\keytool" -genkey -alias tomcat -keyalg RSA
Unix:
$JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
并指定密码值“changeit”。
根据https://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html (这将在您的本地用户目录中创建 a.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" />
我希望这有帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.