使用线程处理多个 Java TCP 客户端
Handling multi Java TCP clients with Threads
我使用 TCP server/client 已经有一段时间了。在连接多个客户端的多个用户时,我实际上擅长 UDP 编程。我尝试在使用线程创建的 TCP 服务器上执行相同的操作,但是每当线程到达这段代码时
String reader = (String)in.readObject();
发生错误,线程停止执行代码,但线程仍在运行程序以保持其活动状态。
不管怎样,这里是完整的源代码:
public class TestServer implements Runnable {
private Thread run, streams, connect, receive, send;
private ServerSocket socket;
private Socket conn;
private ObjectInputStream in;
private ObjectOutputStream out;
private boolean running, incomingMessage = false;
private int port;
public TestServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
console("Server stated on : " + InetAddress.getLocalHost() + " : " + port);
run = new Thread(this, "Run");
run.start();
}
public void run() {
running = true;
connect();
receive();
}
private void connect() {
connect = new Thread("Connect") {
public void run() {
while(running) {
try {
conn = socket.accept();
} catch (IOException e) {
e.printStackTrace();
}
console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort());
try {
setupStreams();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}; connect.start();
}
private void setupStreams() throws IOException {
streams = new Thread("Streams") {
public void run() {
try {
console("Setting up Streams");
out = new ObjectOutputStream(conn.getOutputStream());
out.flush();
in = new ObjectInputStream(conn.getInputStream());
console("Streams are now setup");
incomingMessage = true;
receive.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}; streams.start();
}
private void receive() {
receive = new Thread("Receive") {
public void run() {
while(incomingMessage) {
String message = "";
try {
message = (String) in.readObject();
//This is the only flaw the program
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
console("Client : " + message);
}
}
};
}
private void console(String message) {
System.out.println(message);
}
public static void main(String[] args) {
try {
new TestServer(1234);
} catch (IOException e) {
e.printStackTrace();
}
}
}
仅供参考,我对此并不陌生。该错误是由于服务器在没有接收数据包的情况下开始接收数据包引起的。但是因为线程强制它接收它,所以我在线程中生成错误并且不知道任何其他方法来解决这个问题。所以请帮助。提前致谢。
每个连接不需要 2 个线程。只需一个线程即可。接受连接后,将其传递给工作线程以开始读取。这可以在工作线程中的 while 循环中完成。
尽管可以读取套接字的输入流,但 ObjectInputStream() class 更为敏感。如果有任何错误,它的状态就会损坏,无法使用。
while (true) {
try {
Object input = in.readObject();
message = (String) input;
} catch (IOException e) {
e.printStackTrace();
break; //unrecoverable
} catch (ClassNotFoundException e) {
e.printStackTrace();
break; //unrecoverable
}
console("Client : " + message);
}
使用特定的消息协议而不是发送序列化的 Java 对象是更好的设计。例如,如果您像您的示例一样发送字符串,则可以使用 InputStreamReader 更轻松地将字节转换为字符,并且错误处理更少。
这些资源会对您有所帮助:
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later
Java - Listening to a socket with ObjectInputStream
ObjectInputStream(socket.getInputStream()); does not work
我使用 TCP server/client 已经有一段时间了。在连接多个客户端的多个用户时,我实际上擅长 UDP 编程。我尝试在使用线程创建的 TCP 服务器上执行相同的操作,但是每当线程到达这段代码时
String reader = (String)in.readObject();
发生错误,线程停止执行代码,但线程仍在运行程序以保持其活动状态。 不管怎样,这里是完整的源代码:
public class TestServer implements Runnable {
private Thread run, streams, connect, receive, send;
private ServerSocket socket;
private Socket conn;
private ObjectInputStream in;
private ObjectOutputStream out;
private boolean running, incomingMessage = false;
private int port;
public TestServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
console("Server stated on : " + InetAddress.getLocalHost() + " : " + port);
run = new Thread(this, "Run");
run.start();
}
public void run() {
running = true;
connect();
receive();
}
private void connect() {
connect = new Thread("Connect") {
public void run() {
while(running) {
try {
conn = socket.accept();
} catch (IOException e) {
e.printStackTrace();
}
console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort());
try {
setupStreams();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}; connect.start();
}
private void setupStreams() throws IOException {
streams = new Thread("Streams") {
public void run() {
try {
console("Setting up Streams");
out = new ObjectOutputStream(conn.getOutputStream());
out.flush();
in = new ObjectInputStream(conn.getInputStream());
console("Streams are now setup");
incomingMessage = true;
receive.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}; streams.start();
}
private void receive() {
receive = new Thread("Receive") {
public void run() {
while(incomingMessage) {
String message = "";
try {
message = (String) in.readObject();
//This is the only flaw the program
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
console("Client : " + message);
}
}
};
}
private void console(String message) {
System.out.println(message);
}
public static void main(String[] args) {
try {
new TestServer(1234);
} catch (IOException e) {
e.printStackTrace();
}
}
}
仅供参考,我对此并不陌生。该错误是由于服务器在没有接收数据包的情况下开始接收数据包引起的。但是因为线程强制它接收它,所以我在线程中生成错误并且不知道任何其他方法来解决这个问题。所以请帮助。提前致谢。
每个连接不需要 2 个线程。只需一个线程即可。接受连接后,将其传递给工作线程以开始读取。这可以在工作线程中的 while 循环中完成。
尽管可以读取套接字的输入流,但 ObjectInputStream() class 更为敏感。如果有任何错误,它的状态就会损坏,无法使用。
while (true) {
try {
Object input = in.readObject();
message = (String) input;
} catch (IOException e) {
e.printStackTrace();
break; //unrecoverable
} catch (ClassNotFoundException e) {
e.printStackTrace();
break; //unrecoverable
}
console("Client : " + message);
}
使用特定的消息协议而不是发送序列化的 Java 对象是更好的设计。例如,如果您像您的示例一样发送字符串,则可以使用 InputStreamReader 更轻松地将字节转换为字符,并且错误处理更少。
这些资源会对您有所帮助:
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later
Java - Listening to a socket with ObjectInputStream
ObjectInputStream(socket.getInputStream()); does not work