gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 11:29:18 25 4
gpt4 key购买 nike

这个套接字应用程序工作得很好,直到我添加对服务器的多个客户端连接的支持。然后我从客户端收到 EOFException,并从服务器收到 SocketException: Socket closeed。

服务器.java:

public class Server {

static final int PORT = 8005;
static final int QUEUE = 50;

public Server() {
while (true) {
try (ServerSocket serverSocket = new ServerSocket(PORT, QUEUE);
Socket socket = serverSocket.accept();
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream())) {

Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
output.writeUTF("Hey, this is the server!");
output.flush();
System.out.println(input.readUTF());
} 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();
}

}

客户端.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();
}

}

最佳答案

这里有几个问题:

  1. 您正在为每次循环创建一个新的ServerSocket。对于多客户端服务器,您应该打开一个 ServerSocket 并为每个连接的客户端调用 accept()
  2. 一旦 try block 退出,Try-with-resources 就会关闭它提供的所有资源。您正在创建一个使用 output 但独立于 try block 执行的 Thread,因此执行流程离开 trythread 完成执行之前阻塞,导致socket(和output)在线程能够使用它们之前被关闭。这是其中一种情况,您的资源需要在 try block 的范围之外使用(在您创建的使用它们的线程中),因此 try-with-resources 无法完成您的所有操作为您处理资源。

我会将您的服务器代码重新排列为:

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();
}
}

代码有一些注释来解释一些 Action 。另请注意,socket.close() 调用位于其自己的 try-catch block 中,以确保即使 I/O 流引发异常也能调用它。它可以等效地(或者现在我想起来可能更正确)被放置在 I/O 流 try-catch block 上的 finally block 中。

关于java - 使用套接字和线程时出现 EOFException/SocketException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30553670/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com