使用套接字和线程时出现EOFException / SocketException

时间:2015-05-31 03:54:16

标签: java multithreading sockets socketexception eofexception

此套接字应用程序完全正常,直到我添加对服务器的多个客户端连接的支持。然后我从客户端获得一个EOFException,并从服务器关闭一个SocketException:Socket。

Server.java:

public class Client {

    static final String HOST = "localhost";
    static final int PORT = 8005;

    public Client() {
        try (Socket socket = new Socket(HOST, PORT);
             DataInputStream input = new DataInputStream(socket.getInputStream());
             DataOutputStream output = new DataOutputStream(socket.getOutputStream())
        ) {
            System.out.println(input.readUTF());
            output.writeUTF("Hey, this is the client!");
            output.flush();
        } catch (IOException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Client();
    }

}

Client.java:

Signal

1 个答案:

答案 0 :(得分:1)

这里有几个问题:

  1. 您为循环中的每次传递创建了一个新的ServerSocket。对于多客户端服务器,您应该为每个连接的客户端打开一个ServerSocket并为其调用accept()
  2. 尝试资源会在退出try块后立即关闭其提供的所有资源。您正在创建使用Thread的{​​{1}},但独立于output块执行,因此执行流程在try完成执行之前离开try块,导致thread(和socket)在线程能够使用它们之前关闭。这是需要在output块的范围之外(在您创建的线程中使用它们)使用资源的情况之一,因此try-with-resources无法完成所有资源处理你。
  3. 我会将您的服务器代码重新排列为:

    try

    代码在某种程度上得到了评论,以解释一些举措。另请注意,public class Server { static final int PORT = 8005; static final int QUEUE = 50; public Server() { // create serverSocket once for all connections try (ServerSocket serverSocket = new ServerSocket(PORT, QUEUE)) { while (true) { // accept a client connection, not in a try-with-resources so this will have to be explicitly closed final Socket socket = serverSocket.accept(); Thread thread = new Thread(new Runnable() { @Override public void run() { // limit scope of input/output to where they're actually used try (DataInputStream input = new DataInputStream(socket.getInputStream()); DataOutputStream output = new DataOutputStream(socket.getOutputStream())) { output.writeUTF("Hey, this is the server!"); output.flush(); System.out.println(input.readUTF()); } catch (IOException e) { System.out.println(); e.printStackTrace(); } // implicitly close socket when done with it try { socket.close(); } catch (IOException e) { System.out.println(); e.printStackTrace(); } } }); thread.start(); } } catch (IOException e) { System.out.println(e.getMessage()); e.printStackTrace(); } } public static void main(String[] args) { new Server(); } } 调用位于其自己的try-catch块中,以确保即使I / O流引发异常也会调用它。它可以等效地(或者现在可能更正确地考虑它)放在I / O流try-catch块的socket.close()块中。