此套接字应用程序完全正常,直到我添加对服务器的多个客户端连接的支持。然后我从客户端获得一个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
答案 0 :(得分:1)
这里有几个问题:
ServerSocket
。对于多客户端服务器,您应该为每个连接的客户端打开一个ServerSocket
并为其调用accept()
。try
块后立即关闭其提供的所有资源。您正在创建使用Thread
的{{1}},但独立于output
块执行,因此执行流程在try
完成执行之前离开try
块,导致thread
(和socket
)在线程能够使用它们之前关闭。这是需要在output
块的范围之外(在您创建的线程中使用它们)使用资源的情况之一,因此try-with-resources无法完成所有资源处理你。我会将您的服务器代码重新排列为:
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()
块中。