gpt4 book ai didi

java - 新的 ObjectInputStream 导致挂起/超时

转载 作者:行者123 更新时间:2023-12-02 04:16:41 25 4
gpt4 key购买 nike

我知道这个问题已经被问过好几次了。然而,在遵循所有其他问题的建议后,我仍然不知道问题可能是什么。

我有一个服务器和一个客户端。一个简单的乒乓球程序。在运行服务器和客户端并给它一些时间运行之后,超时异常开始时不时地抛出......

超时是为了防止阻塞,但是,如果删除,则会导致程序停止。

有办法防止这种情况发生吗?

服务器.java

public static void main(String args[]) {
try {
ServerSocket serverSocket = new ServerSocket(3000);
while (true) {
Socket socket = serverSocket.accept();
String message = null;
try {
socket.setSoTimeout(3000);
try (ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream())) {
message = (String) objectInputStream.readObject();
System.out.println("Server received " + message);
}
socket.close();
} catch (IOException | ClassNotFoundException ex) {
//This exception is thrown because it hangs, but why does it hang?
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
if ((message != null) && (message.equals("Ping"))) {
try {
Socket pongSocket = new Socket("localhost", 3000);
pongSocket.setSoTimeout(3000);
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(pongSocket.getOutputStream())) {
objectOutputStream.writeObject("Pong");
objectOutputStream.flush();
System.out.println("Server sent Pong");
}
pongSocket.close();
continue;
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}

Client.java

public static void main(String args[]) {
while (true) {
try {
Socket pingSocket = new Socket("localhost", 3000);
pingSocket.setSoTimeout(3000);
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(pingSocket.getOutputStream())) {
objectOutputStream.writeObject("Ping");
System.out.println("Client sent Ping");
objectOutputStream.flush();
}
pingSocket.close();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

最佳答案

您对服务器和客户端如何使用套接字感到困惑。您可能可以在 stackoverflow 上找到一堆示例,甚至可以通过 Google 找到更多示例,但一般习惯用法是:

server:
create server socket
call accept on server socket
with accepted socket
read request from socket
write response to socket
close accepted socket
loop back to accept

client:
create socket
call connect on socket
write request to socket
read response from socket
close socket

(Java 自动为您执行其中一些操作,例如,当创建套接字并指定主机和端口时,Socket 类会为您调用 connect。)

在您的服务器中,您在读取请求后关闭已接受的套接字,然后创建并连接到一个新套接字以发送响应,这会将响应发送到 localhost:3000 上监听的任何内容,即 < em>你的服务器。此外,在您的客户端中,您正在编写请求但不读取响应,并且在紧密循环中执行此操作,因此您正在创建大量到服务器的连接,这将很快填满接受积压。

真实的生产应用程序会在服务器中使用线程,甚至使用更高级别的库,甚至使用 Tomcat 等整个服务器,但在底层,它们基本上都在执行上述操作,因此理解这一点是很好的。

为了演示,您的代码应如下所示:

服务器.java

public static void main(String args[]) {
try {
ServerSocket serverSocket = new ServerSocket(3000);
while (true) {
Socket socket = serverSocket.accept();
socket.setSoTimeout(250);
String message = null;
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
try {
message = (String) objectInputStream.readObject();
System.out.println("server read: " + message);
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
if ((message != null) && (message.equals("Ping"))) {
try {
objectOutputStream.writeObject("Pong");
System.out.println("server sent pong");
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
objectInputStream.close();
objectOutputStream.close();
socket.close();
}
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}

Client.java

public static void main(String args[]) {
while (true) {
try {
Socket socket = new Socket("localhost", 3000);
String message;
socket.setSoTimeout(250);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject("Ping");
System.out.println("client sent ping");
try (ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream())) {
message = (String) objectInputStream.readObject();
System.out.println("client read: " + message);
}
objectOutputStream.close();
socket.close();
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

关于java - 新的 ObjectInputStream 导致挂起/超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33243247/

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