简体   繁体   English

如何修复:java.net.SocketException:已建立的连接被主机中的软件中止

[英]How to fix: java.net.SocketException: An established connection was aborted by the software in your host machine

Minimal Reproducible Example最小可重现示例

Server.java服务器.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.ServerSocket;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(12345, 3);
        Socket socket = serverSocket.accept(); // incoming request
        new WorkerThread(socket).start();
    }
}

class WorkerThread extends Thread {

    private Socket socket;

    public WorkerThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            oos.flush();
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); // line 28

            // handle the request using oos and ois
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Client.java客户端.java

import java.net.Socket;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Client {
    public static void main(String[] args) throws Exception {
        try (Socket socket = new Socket("192.168.1.3", 12345)) {
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            oos.flush();
            
            // ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); // line 11

            // send some data only using oos
        }
    }
}


Thrown Exception抛出异常

java.net.SocketException: An established connection was aborted by the software in your host machine
        at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:325)
        at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:350)
        at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:803)
        at java.base/java.net.Socket$SocketInputStream.read(Socket.java:966)
        at java.base/java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2908)
        at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2924)
        at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3421)
        at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:959)
        at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:397)
        at WorkerThread.run(Server.java:28)

The WorkerThread seems to be causing the issue, since the SocketException is not thrown if the code in the code of the WorkerThread#run method is placed in the Server#main method. WorkerThread似乎是导致问题的原因,因为如果将WorkerThread#run方法的代码中的代码放在Server#main方法中,则不会引发SocketException See Note below.请参阅下面的注释

The intent here is to have a separate Thread (other than the main Thread of the Server) handle each request as it comes, therefore the WorkerThread receives a reference to the Socket associated with the incoming connection.这里的目的是让一个单独的线程(除了服务器的主线程)处理每个请求,因此WorkerThread接收对与传入连接关联的Socket的引用。

The WorkerThread needs to open both oos and ois (even though they might not be both strictly needed for communication) because opening only the ois won't work. WorkerThread需要同时打开oosois (即使它们可能并非都严格需要用于通信),因为只打开ois是行不通的。 Further reading on why this happens . 进一步阅读为什么会发生这种情况

What is the underlying cause of this issue?这个问题的根本原因是什么? Is there a way to fix the problem other than the hacky (?) solution presented below?除了下面介绍的 hacky (?) 解决方案之外,还有其他方法可以解决问题吗?


Note笔记

Running the above Client with this Server does not throw the Exception:使用此服务器运行上述客户端不会引发异常:

NonThreadedServer.java NonThreadedServer.java

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.ServerSocket;

public class NonThreadedServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(12345, 3);
        Socket socket = serverSocket.accept(); // incoming request

        try {
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            oos.flush();
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());

            // handle the request using oos and ois
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Solution解决方案

Uncomment line 11 of Client , ie create an ObjectInputStream , even though it is not strictly needed for the communication:取消注释Client的第 11 行,即创建一个ObjectInputStream ,即使通信并不严格需要它:

Client.java客户端.java

import java.net.Socket;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Client {
    public static void main(String[] args) throws Exception {
        try (Socket socket = new Socket("192.168.1.3", 12345)) {
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            oos.flush();
            
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); // line 11

            // send some data only using oos
        }
    }
}

As mentioned in the question, I don't know what the underlying issue is or whether this solution is the correct one.如问题中所述,我不知道根本问题是什么,也不知道这个解决方案是否正确。 If it isn't, I'll make sure to mark another answer as the accepted one.如果不是,我会确保将另一个答案标记为已接受的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java sun.net.HttpServer写入OutputStream会引发IOException“已建立的连接已被主机中的软件中止” - Java sun.net.HttpServer writing to OutputStream throws IOException “An established connection was aborted by the software in your host machine” android主机中的软件中止了已建立的连接 - android An established connection was aborted by the software in your host machine 已建立的连接被主机中的软件中止 tomcat jackson - An established connection was aborted by the software in your host machine tomcat jackson 从Java代码将文件复制到Hadoop HDFS时,“主机中的软件中止了已建立的连接” - “An established connection was aborted by the software in your host machine” while copying file to Hadoop HDFS from Java code 使用java nio socket时,“已建立的连接被主机中的软件中止” - 'An established connection was aborted by the software in your host machine' when using java nio socket Spring Reactive:java.io.IOException:当我关闭连接时,主机中的软件中止了已建立的连接 - Spring Reactive: java.io.IOException: An established connection was aborted by the software in your host machine, when I close the connection System.IO.IOException:无法将数据写入传输连接:主机中的软件中止了已建立的连接 - System.IO.IOException: Unable to write data to the transport connection: An established connection was aborted by the software in your host machine 为什么gRPC仅在Windows上每秒每秒抛出“已建立的连接已被主机中的软件中止”? - Why does gRPC throw an “established connection was aborted by the software in your host machine” every second on windows only? Spring DeferredResult导致IOException:已建立的连接被主机中的软件中止 - Spring DeferredResult causes IOException: An established connection was aborted by the software in your host machine apr_socket_recv:建立的连接被主机中的软件中止了 - apr_socket_recv: An established connection was aborted by the software in your host machine
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM