我知道这个问题已经被问了好几次了。但是,在遵循所有其他问题的建议之后,我仍然不知道问题可能是什么。
我有服务器和客户端。一个简单的ping / pong程序。在运行服务器然后运行客户端并给它一些时间来运行它之后,超时异常会不时地被抛出......
超时是为了防止阻塞,但是,如果删除,则会导致程序停止。
有没有办法防止这种情况发生?
Server.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);
}
}
}
答案 0 :(得分:2)
您对服务器和客户端如何使用套接字感到困惑。您可以在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这样的整个服务器,但在底层,他们基本上都在做上述事情,所以理解它是很好的。
为了演示,这就是您的代码应该是这样的:
<强> Server.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);
}
}
}
答案 1 :(得分:0)
你没有任何限制发送者的速度。一目了然,我会说你只是通过发送请求比处理它们更快来压倒服务器。你的服务器&#34;在套接字上收听不能与非受限制的&#34;客户进行竞争&#34;。