package 网络.核心类; import java.net.*; import java.io.*; import java.util.Scanner; public class Client { public static void main(String[] args) { try (Socket socket = new Socket("localhost", 12345); // 连接到服务器的IP和端口 PrintWriter out = new PrintWriter(socket.getOutputStream(), true); // 用于发送数据 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 用于接收数据 Scanner scanner = new Scanner(System.in)) { // 用于读取键盘输入 System.out.println("Connected to server. Type your message and press enter to send. Type 'exit' to quit."); while (true) { System.out.print("Client: "); String userInput = scanner.nextLine(); // 读取用户输入 if (userInput.equalsIgnoreCase("exit")) { System.out.println("Exiting client..."); break; // 退出循环 } // TODO: 扩展用户输入处理,支持不同命令(如 "echo <消息>"、"time"、"quit")。例如,提示用户可用命令并根据输入类型发送适当的消息。 // 提示:您可以在这里添加代码来解析用户输入,并修改发送逻辑。 out.println(userInput); // 通过Socket发送消息到服务器 String response = in.readLine(); // 通过Socket读取服务器响应 System.out.println("Server response: " + response); // 显示响应 // TODO: 扩展响应处理,根据服务器返回的不同响应类型进行处理(如显示时间或错误消息)。确保处理 null 或异常情况。 } } catch (IOException e) { System.err.println("Connection error: " + e.getMessage()); // 处理连接异常 } } } package 网络.核心类; import java.net.*; import java.io.*; public class Server { public static void main(String[] args) { try (ServerSocket serverSocket = new ServerSocket(12345)) { // 绑定到端口12345 System.out.println("Server started. Listening on port 12345..."); while (true) { // 无限循环,等待客户端连接 Socket clientSocket = serverSocket.accept(); // 接受客户端连接,返回一个Socket对象 System.out.println("Client connected: " + clientSocket.getInetAddress()); // 使用Socket处理客户端通信(这里使用独立的线程处理每个客户端,避免阻塞) new Thread(() -> { try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) { String message; while ((message = in.readLine()) != null) { // 读取客户端发送的消息 System.out.println("Received from client: " + message); // TODO: 扩展消息处理逻辑,支持简单协议。例如,根据消息类型执行操作: // - 如果消息以 "echo" 开头,返回回显消息。 // - 如果消息是 "time",返回当前系统时间。 // - 如果消息是 "quit",断开连接。 // 提示:使用 if-else 语句或 switch 表达式来处理不同命令。确保处理无效命令,返回错误消息。 out.println("Echo: " + message); // 默认回显逻辑,学生需要修改此部分 } } catch (IOException e) { System.err.println("Error handling client: " + e.getMessage()); } finally { try { clientSocket.close(); // 关闭Socket } catch (IOException e) { e.printStackTrace(); } } }).start(); // 启动新线程处理客户端 } } catch (IOException e) { System.err.println("Server error: " + e.getMessage()); // 处理异常,如端口被占用 } } }补充完善上述代码
时间: 2025-08-03 12:07:10 浏览: 8
<think>我们有一个Java服务器和客户端代码需要完善。根据引用的内容,我们有一个简单的服务器示例(SimpleServer),它使用ServerSocket并设置了连接请求队列长度。现在,我们需要为客户端和服务器添加命令处理逻辑(支持echo,time,quit命令),完善错误处理,并支持多线程(使得服务器可以同时处理多个客户端)。步骤:1.服务器端:-使用多线程:为每个客户端连接创建一个新的线程来处理。-在客户端处理线程中,读取客户端发送的命令,解析并执行相应的操作。-支持的命令:-echo<message>:返回相同的消息。-time:返回当前服务器时间。-quit:关闭当前客户端连接。-需要完善错误处理(例如,命令解析错误、IO异常等)。2.客户端:-连接服务器,从控制台读取用户输入的命令,发送到服务器。-接收服务器的响应并显示。-当输入quit命令时,关闭连接并退出。3.协议设计:-简单的文本协议,每行一个命令(使用BufferedReader的readLine和PrintWriter的println)。4.错误处理:-客户端和服务器都需要捕获并处理异常(如SocketException,IOException等)。-对于未知命令,服务器应返回错误消息。实现:服务器端代码(多线程):```javaimportjava.io.*;importjava.net.*;importjava.text.SimpleDateFormat;importjava.util.Date;publicclassCommandServer{publicstaticvoidmain(String[]args)throwsException{ServerSocketserverSocket=newServerSocket(8888,10);System.out.println("Serverstartedonport8888");while(true){SocketclientSocket=serverSocket.accept();System.out.println("Acceptedconnectionfrom"+clientSocket.getInetAddress());//为每个客户端创建一个新线程newThread(newClientHandler(clientSocket)).start();}}privatestaticclassClientHandlerimplementsRunnable{privatefinalSocketclientSocket;publicClientHandler(Socketsocket){this.clientSocket=socket;}@Overridepublicvoidrun(){try(BufferedReaderin=newBufferedReader(newInputStreamReader(clientSocket.getInputStream()));PrintWriterout=newPrintWriter(clientSocket.getOutputStream(),true)){StringinputLine;while((inputLine=in.readLine())!=null){System.out.println("Receivedfromclient:"+inputLine);//解析命令String[]tokens=inputLine.split("",2);Stringcommand=tokens[0].toLowerCase();switch(command){case"echo":if(tokens.length<2){out.println("Error:echocommandrequiresanargument");}else{out.println(tokens[1]);}break;case"time":SimpleDateFormatdateFormat=newSimpleDateFormat("yyyy-MM-ddHH:mm:ss");out.println(dateFormat.format(newDate()));break;case"quit":out.println("Bye");return;//退出循环,关闭连接default:out.println("Error:unknowncommand");break;}}}catch(IOExceptione){System.err.println("Errorhandlingclient:"+e.getMessage());}finally{try{clientSocket.close();}catch(IOExceptione){System.err.println("Errorclosingclientsocket:"+e.getMessage());}}}}}```客户端代码:```javaimportjava.io.*;importjava.net.*;importjava.util.Scanner;publicclassCommandClient{publicstaticvoidmain(String[]args){Stringhost="localhost";intport=8888;try(Socketsocket=newSocket(host,port);PrintWriterout=newPrintWriter(socket.getOutputStream(),true);BufferedReaderin=newBufferedReader(newInputStreamReader(socket.getInputStream()));Scannerscanner=newScanner(System.in)){System.out.println("Connectedtoserver.Entercommands(echo,time,quit):");StringuserInput;while(true){System.out.print(">");userInput=scanner.nextLine();out.println(userInput);//如果用户输入quit,则退出循环if(userInput.equalsIgnoreCase("quit")){break;}//读取并打印服务器响应Stringresponse=in.readLine();System.out.println("Server:"+response);}}catch(UnknownHostExceptione){System.err.println("Unknownhost:"+host);}catch(IOExceptione){System.err.println("I/Oerror:"+e.getMessage());}}}```说明:1.服务器使用多线程处理每个客户端连接(ClientHandler实现了Runnable接口)。2.服务器解析客户端发送的命令,根据命令类型返回响应。3.客户端通过控制台输入命令,发送到服务器并显示响应。4.当客户端发送"quit"命令时,服务器会关闭与该客户端的连接,客户端也会退出。注意事项:-在服务器端,每个客户端连接都会创建一个新线程,当有大量客户端时需要考虑线程池(这里为了简化没有使用线程池)。-错误处理:捕获了IO异常并打印错误信息,但实际应用中可能需要更详细的错误处理。-协议:使用简单的行分隔协议(每行一个命令)。改进点(如果需要):-使用线程池(如Executors.newCachedThreadPool())来管理线程,避免资源耗尽。-添加更复杂的命令或协议(如支持参数解析等)。-增加日志记录。相关问题:§§相关问题§§1.如何优化上述服务器代码以支持大量并发连接?2.除了多线程,还有哪些方法可以提高Java服务器性能?3.如何设计一个更健壮的网络协议来支持复杂命令?</think>
以下是为 Java Socket 客户端/服务器添加命令解析、多线程和错误处理的实现方案,结合了引用中提到的连接队列管理和指令处理逻辑:
### 服务端实现(支持多线程和命令解析)
```java
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
public class CommandServer {
private static final int MAX_QUEUE = 10; // 连接请求队列长度[^1]
public static void main(String[] args) {
ExecutorService threadPool = Executors.newCachedThreadPool();
try (ServerSocket serverSocket = new ServerSocket(8888, MAX_QUEUE)) {
System.out.println("Server started. Commands: echo|time|quit");
while (!Thread.interrupted()) {
Socket clientSocket = serverSocket.accept();
threadPool.submit(new ClientHandler(clientSocket));
}
} catch (IOException e) {
System.err.println("Server error: " + e.getMessage());
} finally {
threadPool.shutdown();
}
}
private static class ClientHandler implements Runnable {
private final Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
String clientAddr = socket.getInetAddress().toString();
System.out.println("Client connected: " + clientAddr);
String input;
while ((input = in.readLine()) != null) {
System.out.println("Received: " + input + " from " + clientAddr);
// 命令解析逻辑
String[] cmd = input.trim().split("\\s+", 2);
switch (cmd[0].toLowerCase()) {
case "echo":
if (cmd.length > 1) out.println("ECHO: " + cmd[1]);
else out.println("ERROR: Missing message");
break;
case "time":
out.println("TIME: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
break;
case "quit":
out.println("BYE");
return; // 结束客户端会话
default:
out.println("ERROR: Unsupported command");
}
}
} catch (IOException e) {
System.err.println("Client handling error: " + e.getMessage());
} finally {
try { socket.close(); } catch (IOException ignored) {}
}
}
}
}
```
### 客户端实现(命令交互)
```java
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class CommandClient {
public static void main(String[] args) {
try (Socket socket = new Socket("localhost", 8888);
Scanner userInput = new Scanner(System.in);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
System.out.println("Connected to server. Enter commands (echo, time, quit)");
new Thread(() -> { // 独立的响应接收线程
try {
String response;
while ((response = in.readLine()) != null) {
System.out.println("Server >> " + response);
}
} catch (IOException e) {
System.err.println("Receive error: " + e.getMessage());
}
}).start();
// 用户命令输入
while (true) {
System.out.print("Client >> ");
String command = userInput.nextLine();
out.println(command);
if ("quit".equalsIgnoreCase(command)) {
System.out.println("Disconnecting...");
break;
}
}
} catch (UnknownHostException e) {
System.err.println("Unknown host: " + e.getMessage());
} catch (ConnectException e) {
System.err.println("Connection refused. Is server running?");
} catch (IOException e) {
System.err.println("I/O error: " + e.getMessage());
}
}
}
```
### 关键功能说明
1. **协议支持**(基于文本行协议)
- `echo <message>`: 返回消息内容
- `time`: 返回服务器当前时间
- `quit`: 终止连接
2. **多线程管理**
- 使用线程池处理并发连接
- 每个客户端连接独立线程处理
- 客户端使用分离的输入/输出线程
3. **错误处理机制**
```java
// 连接错误处理
catch (ConnectException e) {
System.err.println("Connection refused. Is server running?");
}
// 命令错误处理
case "echo":
if (cmd.length > 1) out.println("ECHO: " + cmd[1]);
else out.println("ERROR: Missing message"); // 参数错误
```
4. **连接队列管理**[^1]
```java
new ServerSocket(8888, MAX_QUEUE); // 控制等待连接数
```
### 使用示例流程
```
// 服务端输出
Server started. Commands: echo|time|quit
Client connected: /127.0.0.1
Received: echo Hello from /127.0.0.1
// 客户端输入
Client >> echo Hello
Server >> ECHO: Hello
Client >> time
Server >> TIME: 2023-08-30 14:30:45
```
### 注意事项
1. 当需要扩展新命令时,在服务端 `switch-case` 添加新分支
2. 如需支持更复杂协议,可添加协议解析层(如引用[2]中的过滤机制)
3. 对于生产环境建议增加:
- 连接超时控制
- 协议版本校验
- 输入内容消毒(防止注入攻击)
阅读全文