【问题标题】:java.net.SocketException: Software caused connection abort: socket write error when resubmitting the requestjava.net.SocketException:软件导致连接中止:重新提交请求时套接字写入错误
【发布时间】:2018-09-20 13:55:13
【问题描述】:

使用套接字解决这个问题。我编写了 Http 和 TCP 服务器的实现。 HTTP 工作完全正常,所以我可以一一向服务器发送请求。 TCP服务器不能说的是,第一个请求离开并被正确处理,但是当您尝试发送以下请求时,抛出此异常:

java.net.SocketException: Software caused connection abort: socket write error
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:134)
    at java.io.DataOutputStream.writeBytes(DataOutputStream.java:276)
    at Main.main(Main.java:24)

之后,客户端关闭,服务器端继续工作。HTTP和TCP从同一个Server类实现,启动服务器。

我的服务器:

public abstract class Server implements Runnable {

    private final Socket clientSocket;

    public Server(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
             BufferedWriter output = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream()))) {
            String req = getRequest(reader);
            setResponse(output, req);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

启动服务器的类:

public class RunServer extends Thread {
    private final int port;
    private ExecutorService executorService;
    private String serverType;
    private ServerFactoryContainer serverFactoryContainer;

    public RunServer(String serverType, int port) {
        this.port = port;
        this.executorService = Executors.newFixedThreadPool(4);
        this.serverType = serverType;
        this.serverFactoryContainer = new ServerFactoryContainer();
    }

    @Override
    public void run() {
            try {
                ServerSocket serverSocket = new ServerSocket(port);
                while (!isInterrupted()) {
                    Socket clientSocket;
                    try {
                        clientSocket = serverSocket.accept();
                        executorService.execute(serverFactoryContainer.getServerFactory(serverType).createServer(clientSocket));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

TCP 客户端:

public class Main {
    public static void main(String[] args) throws IOException {
        String req;
        String resp;

        try (Socket clientSocket = new Socket(InetAddress.getLocalHost(), Constants.ServerConstant.TCP_PORT);
             BufferedReader inFromClient = new BufferedReader(new InputStreamReader(System.in));
             DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
             BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {
            while (true) {
                System.out.println("Write command [get count] or [get item]");
                req = inFromClient.readLine().toLowerCase();
                outToServer.writeBytes(req + "\n");  // I get an exception here when I send a request to the server

                resp = inFromServer.readLine();
                if (!resp.isEmpty()) {
                    System.out.println(resp);
                }
                if (req.equals("exit")) {
                    System.exit(1);
                }
            }
        }
    }

为什么我在向 TCP 服务器重新提交请求时会收到上面指出的异常,为什么在向 HTTP 服务器发送第二个请求时没有抛出此异常?

@Override
    protected String getRequest(BufferedReader input) throws IOException {
        return input.readLine();
    }

    @Override
    protected void setResponse(BufferedWriter output, String request) throws IOException {
        String result = serverCommandController.execute(RequestParser.tcpParserCommand(request));
        output.write(result);
        output.flush();
    }

【问题讨论】:

    标签: java sockets server


    【解决方案1】:

    您在客户端完成之前关闭客户端连接。在你的服务器类中试试这个:

    @Override
    public void run()
    {
      try (BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); BufferedWriter output = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream())))
      {
        while (clientSocket.isConnected())
        {
          String req = getRequest(reader);
          setResponse(output, req);
        }
      }
      catch (IOException e)
      {
        e.printStackTrace();
      }
      finally
      {
        try
        {
          clientSocket.close();
        }
        catch (IOException e)
        {
          e.printStackTrace();
        }
      }
    }
    

    【讨论】:

    • 我试过了,但后来我陷入了无环循环。因此,我这样做了。所以我在最后一个块中添加了一个测试,在那里我检查!是连接;如果条件通过则关闭套接字。但错误仍在继续
    • 您希望处于一个循环中,直到您的客户端关闭连接。你能发布你的getRequestsetResponse方法吗?
    • 是的,我应聘了
    • 当您在 setResponse 方法中执行 output.write(result); 时,result 是否以 '\n' 结尾?因为您的客户端正在读取一行,所以它在检测到换行之前不会停止缓冲。
    【解决方案2】:

    您的服务器在发送响应后似乎关闭了套接字。之后,客户端将无法在不打开新连接的情况下发送进一步的请求。通常,服务器允许客户端控制连接的命运,以便客户端可以发送多个请求。您的客户端可以发送“关闭”请求以向服务器指示客户端打算关闭套接字并且不期望响应。

    【讨论】:

    • 好的,但是为什么 HTTP 服务器可以正常工作,我可以重新发送请求吗?而且我只在一个地方关闭了套接字,当我删除它时,没有任何改变,不包括使用资源的自动关闭尝试)但我没有关闭服务器套接字。我不明白我可能错在哪里:(
    • 我在 finally 子句中查看您的 Server 类。我看不到 HTTP 服务器,但我怀疑它没有这样做。
    猜你喜欢
    • 2011-02-21
    • 2012-12-21
    • 2019-07-27
    • 2011-01-04
    • 2014-10-12
    • 2016-03-04
    • 2011-01-08
    相关资源
    最近更新 更多