【发布时间】:2018-10-10 00:11:07
【问题描述】:
最近,我一直在玩 Java 的网络和线程功能,作为背景,我正在尝试开发一个多线程聊天应用程序。
问题在于,当客户端发送使用错误格式的消息时,例如: “UserID#Message”而不是“UserID*Message”抛出异常,线程完全停止,客户端需要关闭他的会话并重新打开它以重新建立与服务器的连接,而不是在错误后恢复,我无法恢复它。
这是服务器代码:
package AdvanceThreading.Server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
private ServerSocket serverSocket;
private Socket socket;
private DataInputStream messageFromClientToHandler;
private DataOutputStream messageFromHandlerToRecipient;
private int port;
private static int userID;
private ArrayList<ClientHandler> clientList;
public Server(int port) {
this.port = port;
this.userID = 0;
clientList = new ArrayList<>();
this.initialize();
}
public void initialize() {
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
messageFromClientToHandler = new DataInputStream(socket.getInputStream());
messageFromHandlerToRecipient = new DataOutputStream(socket.getOutputStream());
String userName = messageFromClientToHandler.readUTF();
messageFromHandlerToRecipient.writeInt(userID);
ClientHandler client = new ClientHandler(userID, userName, this, socket, messageFromClientToHandler, messageFromHandlerToRecipient);
clientList.add(client);
//Should set client.setUncaughtExceptionHandler();
client.start();
userID = userID + 1;
} catch (IOException e) {
e.printStackTrace();
}
}
}
public ServerSocket getServerSocket() {
return serverSocket;
}
public Socket getSocket() {
return socket;
}
public DataInputStream getMessageFromClientToHandler() {
return messageFromClientToHandler;
}
public DataOutputStream getMessageFromHandlerToRecipient() {
return messageFromHandlerToRecipient;
}
public int getPort() {
return port;
}
public static int getUserID() {
return userID;
}
public ArrayList<ClientHandler> getClientList() {
return clientList;
}
public static void main(String[] args) {
Server server = new Server(5050);
}
}
客户端处理程序代码:
package AdvanceThreading.Server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.StringTokenizer;
public class ClientHandler extends Thread {
private int clientID;
private String clientName;
private boolean loggedIn;
private Socket socket;
private Server server;
private DataInputStream messageFromClientToHandler;
private DataOutputStream messageFromHandlerToRecipient;
public ClientHandler(int clientID, String clientName, Server server, Socket socket, DataInputStream messageFromClientToHandler, DataOutputStream messageFromHandlerToRecipient) {
this.clientID = clientID;
this.clientName = clientName;
this.loggedIn = true;
this.server = server;
this.socket = socket;
this.messageFromClientToHandler = messageFromClientToHandler;
this.messageFromHandlerToRecipient = messageFromHandlerToRecipient;
}
@Override
public void run() {
String receivedFromClient;
StringTokenizer tokenize = null;
while (true) {
try {
receivedFromClient = messageFromClientToHandler.readUTF();
System.out.println(receivedFromClient);
tokenize = new StringTokenizer(receivedFromClient, "#");
String recipient = tokenize.nextToken();
int recipientID = Integer.parseInt(tokenize.nextToken());
String message = tokenize.nextToken();
//Need to handle exception of client not found.
for (ClientHandler client : server.getClientList()) {
if (client.getClientID() == recipientID && client.isLoggedIn()) {
client.getMessageFromHandlerToRecipient().writeUTF(this.clientName + ": " + message);
break;
}
}
} catch (IOException e) {
while (tokenize != null && tokenize.hasMoreTokens())
tokenize.nextToken();
e.printStackTrace();
}
}
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public boolean isLoggedIn() {
return loggedIn;
}
public void setLoggedIn(boolean loggedIn) {
this.loggedIn = loggedIn;
}
public int getClientID() {
return clientID;
}
public Socket getSocket() {
return socket;
}
public Server getServer() {
return server;
}
public DataInputStream getMessageFromClientToHandler() {
return messageFromClientToHandler;
}
public DataOutputStream getMessageFromHandlerToRecipient() {
return messageFromHandlerToRecipient;
}
}
如果使用终端的客户端(例如:CMD)出现错误,我想做的主要事情是我想捕获错误并处理它,并在同一个终端上恢复他的会话,这样他就不必重新连接到服务器。
【问题讨论】:
-
旁注:有 IO 问题的终端会话可能会引发异常,在这种情况下,无法重用相同的终端会话
-
那么,基本上由我来确保客户不会犯错?
-
您可以通过添加运行时异常 try catch 块来轻松解决任何与转换相关的异常,我会在几秒钟内为您删除代码
-
一旦线程终止(即未捕获的异常),它就无法恢复。在线程上运行的代码内部必须有逻辑以“处理错误并适当地继续”或在线程外部“启动新线程”。捕获异常不会“暂停”线程;相反,这只是与 if-something-failed-then 相同的标准流控制操作。
标签: java multithreading networking error-handling