消息发送后,客户端应该如何正确等待服务器的响应?
How should a client properly wait for a reponse from the server after a message has been sent?
我正在尝试让客户端和服务器正确回显消息。
这意味着客户端应该向服务器发送一条消息,服务器应该接收并将相同的消息发送回客户端,然后客户端打印出接收到的消息。
我无法让客户端正确等待服务器完成发送响应,然后客户端才能接收响应并打印出来。
唯一可行的方法是当我注释掉 EchoClient2.java RECEIVE MESSAGE 代码时。
EchoClient2.java
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
public class EchoClient2 {
private Socket clientSocket;
private DataOutputStream out;
private DataInputStream in;
private void start(String ip, int port) {
try {
clientSocket = new Socket(ip, port);
out = new DataOutputStream(clientSocket.getOutputStream());
in = new DataInputStream(clientSocket.getInputStream());
} catch (IOException e) {
System.out.println("Error when initializing connection");
}
}
private void sendMessage(String message) throws IOException {
//SENDING MESSAGE
byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
System.out.println("Client will send the text: " + message);
out.write(messageBytes);
out.flush();
//RECEIEVE MESSAGE - Doesn't give server a chance to respond?
byte[] data = new byte[8];
ByteArrayOutputStream getData = new ByteArrayOutputStream();
int numBytes;
while ((numBytes = in.read(data)) != -1) {
getData.write(data, 0, numBytes);
}
byte[] message2Bytes = getData.toByteArray();
String text = new String(message2Bytes, StandardCharsets.UTF_8);
System.out.println("Server sent the client text: " + text);
}
private void stop() {
try {
in.close();
out.close();
clientSocket.close();
} catch (IOException e) {
System.out.println("error when closing");
}
}
public static void main(String[] args) throws IOException {
EchoClient2 client = new EchoClient2();
client.start("127.0.0.1", 4444);
client.sendMessage("exit");
client.stop();
}
}
EchoServer2.java
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.io.*;
public class EchoServer2 {
private ServerSocket serverSocket;
private Socket clientSocket;
private DataOutputStream out;
private DataInputStream in;
public void start(int port) {
try {
serverSocket = new ServerSocket(port);
clientSocket = serverSocket.accept();
out = new DataOutputStream(clientSocket.getOutputStream());
in = new DataInputStream(clientSocket.getInputStream());
} catch (IOException e) {
System.out.println("Error when establishing/accepting server connection");
}
}
private void actionMessage() throws IOException {
//RECEIEVE MESSAGE
byte[] data = new byte[8];
ByteArrayOutputStream getData = new ByteArrayOutputStream();
int numBytes;
while ((numBytes = in.read(data)) != -1) {
getData.write(data, 0, numBytes);
}
byte[] messageBytes = getData.toByteArray();
String text = new String(messageBytes, StandardCharsets.UTF_8);
System.out.println("Server got " + text + " and will send this back to client");
//SENDING BACK SAME MESSAGE
out.write(messageBytes);
out.flush();
}
public void stop() {
try {
in.close();
out.close();
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) throws IOException {
EchoServer2 server = new EchoServer2();
System.out.println("Now waiting for incoming connection...");
server.start(4444);
server.actionMessage();
server.stop();
}
}
有人知道为什么这不能正常工作吗?
服务器正在以 8 字节块的形式读取客户端的输入直到客户端断开连接(它没有这样做),然后写回响应。服务器需要在每个块 到达时写回 ,然后在客户端断开连接后断开连接。这意味着在 while
阅读循环中移动 out.write()
。
private void actionMessage() throws IOException {
byte[] data = new byte[8];
int numBytes;
while ((numBytes = in.read(data)) != -1) {
out.write(data, 0, numBytes);
out.flush();
}
}
这对于简单的回显服务器来说很好,但对于更现实的消息服务器来说并不是很有用。您需要一个更明确的协议来来回交换消息,而不必失去它们之间的连接(除非您想要实现无状态协议,如 HTTP,它允许请求之间断开连接)。例如:
客户:
private void sendMessage(String message) throws IOException {
System.out.println("Client will send the text: " + message);
//SEND MESSAGE
byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
out.writeInt(messageBytes.length);
out.write(messageBytes);
out.flush();
//RECEIVE MESSAGE
int len = in.readInt();
byte[] data = new byte[len];
in.readFully(data);
String text = new String(data, StandardCharsets.UTF_8);
System.out.println("Server sent the client text: " + text);
}
public static void main(String[] args) throws IOException {
EchoClient2 client = new EchoClient2();
client.start("127.0.0.1", 4444);
try {
client.sendMessage("hello");
client.sendMessage("exit");
} catch (IOException e) {
...
}
client.stop();
}
服务器:
private void actionMessage() throws IOException {
//RECEIVE MESSAGE
int len = in.readInt();
byte[] data = new byte[len];
in.readFully(data);
String text = new String(data, StandardCharsets.UTF_8);
System.out.println("Server got " + text + " and will send this back to client");
//SEND MESSAGE
data = text.getBytes(StandardCharsets.UTF_8);
out.writeInt(data.length);
out.write(data);
out.flush();
}
public static void main(String[] args) throws IOException {
EchoServer2 server = new EchoServer2();
System.out.println("Now waiting for incoming connection...");
server.start(4444);
while (true) {
try {
server.actionMessage();
} catch (IOException e) {
...
break;
}
}
server.stop();
}
我正在尝试让客户端和服务器正确回显消息。
这意味着客户端应该向服务器发送一条消息,服务器应该接收并将相同的消息发送回客户端,然后客户端打印出接收到的消息。
我无法让客户端正确等待服务器完成发送响应,然后客户端才能接收响应并打印出来。
唯一可行的方法是当我注释掉 EchoClient2.java RECEIVE MESSAGE 代码时。
EchoClient2.java
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
public class EchoClient2 {
private Socket clientSocket;
private DataOutputStream out;
private DataInputStream in;
private void start(String ip, int port) {
try {
clientSocket = new Socket(ip, port);
out = new DataOutputStream(clientSocket.getOutputStream());
in = new DataInputStream(clientSocket.getInputStream());
} catch (IOException e) {
System.out.println("Error when initializing connection");
}
}
private void sendMessage(String message) throws IOException {
//SENDING MESSAGE
byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
System.out.println("Client will send the text: " + message);
out.write(messageBytes);
out.flush();
//RECEIEVE MESSAGE - Doesn't give server a chance to respond?
byte[] data = new byte[8];
ByteArrayOutputStream getData = new ByteArrayOutputStream();
int numBytes;
while ((numBytes = in.read(data)) != -1) {
getData.write(data, 0, numBytes);
}
byte[] message2Bytes = getData.toByteArray();
String text = new String(message2Bytes, StandardCharsets.UTF_8);
System.out.println("Server sent the client text: " + text);
}
private void stop() {
try {
in.close();
out.close();
clientSocket.close();
} catch (IOException e) {
System.out.println("error when closing");
}
}
public static void main(String[] args) throws IOException {
EchoClient2 client = new EchoClient2();
client.start("127.0.0.1", 4444);
client.sendMessage("exit");
client.stop();
}
}
EchoServer2.java
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.io.*;
public class EchoServer2 {
private ServerSocket serverSocket;
private Socket clientSocket;
private DataOutputStream out;
private DataInputStream in;
public void start(int port) {
try {
serverSocket = new ServerSocket(port);
clientSocket = serverSocket.accept();
out = new DataOutputStream(clientSocket.getOutputStream());
in = new DataInputStream(clientSocket.getInputStream());
} catch (IOException e) {
System.out.println("Error when establishing/accepting server connection");
}
}
private void actionMessage() throws IOException {
//RECEIEVE MESSAGE
byte[] data = new byte[8];
ByteArrayOutputStream getData = new ByteArrayOutputStream();
int numBytes;
while ((numBytes = in.read(data)) != -1) {
getData.write(data, 0, numBytes);
}
byte[] messageBytes = getData.toByteArray();
String text = new String(messageBytes, StandardCharsets.UTF_8);
System.out.println("Server got " + text + " and will send this back to client");
//SENDING BACK SAME MESSAGE
out.write(messageBytes);
out.flush();
}
public void stop() {
try {
in.close();
out.close();
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) throws IOException {
EchoServer2 server = new EchoServer2();
System.out.println("Now waiting for incoming connection...");
server.start(4444);
server.actionMessage();
server.stop();
}
}
有人知道为什么这不能正常工作吗?
服务器正在以 8 字节块的形式读取客户端的输入直到客户端断开连接(它没有这样做),然后写回响应。服务器需要在每个块 到达时写回 ,然后在客户端断开连接后断开连接。这意味着在 while
阅读循环中移动 out.write()
。
private void actionMessage() throws IOException {
byte[] data = new byte[8];
int numBytes;
while ((numBytes = in.read(data)) != -1) {
out.write(data, 0, numBytes);
out.flush();
}
}
这对于简单的回显服务器来说很好,但对于更现实的消息服务器来说并不是很有用。您需要一个更明确的协议来来回交换消息,而不必失去它们之间的连接(除非您想要实现无状态协议,如 HTTP,它允许请求之间断开连接)。例如:
客户:
private void sendMessage(String message) throws IOException {
System.out.println("Client will send the text: " + message);
//SEND MESSAGE
byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
out.writeInt(messageBytes.length);
out.write(messageBytes);
out.flush();
//RECEIVE MESSAGE
int len = in.readInt();
byte[] data = new byte[len];
in.readFully(data);
String text = new String(data, StandardCharsets.UTF_8);
System.out.println("Server sent the client text: " + text);
}
public static void main(String[] args) throws IOException {
EchoClient2 client = new EchoClient2();
client.start("127.0.0.1", 4444);
try {
client.sendMessage("hello");
client.sendMessage("exit");
} catch (IOException e) {
...
}
client.stop();
}
服务器:
private void actionMessage() throws IOException {
//RECEIVE MESSAGE
int len = in.readInt();
byte[] data = new byte[len];
in.readFully(data);
String text = new String(data, StandardCharsets.UTF_8);
System.out.println("Server got " + text + " and will send this back to client");
//SEND MESSAGE
data = text.getBytes(StandardCharsets.UTF_8);
out.writeInt(data.length);
out.write(data);
out.flush();
}
public static void main(String[] args) throws IOException {
EchoServer2 server = new EchoServer2();
System.out.println("Now waiting for incoming connection...");
server.start(4444);
while (true) {
try {
server.actionMessage();
} catch (IOException e) {
...
break;
}
}
server.stop();
}