
在java中构建tcp客户端-服务器应用程序时,实现连续的数据交换直至特定条件满足(例如收到“stop”指令或连接关闭)是一个常见的需求。原始代码中存在一个常见误区,即服务器在处理完一个客户端请求后,外层循环会立即尝试接受新的客户端连接,而非持续与当前客户端通信。这导致服务器无法处理同一客户端的后续请求,而客户端则会因服务器未响应而挂起。
原服务器代码的 while(true) 循环用于不断接受新的客户端连接。一旦 welcomeSocket.accept() 返回一个 Socket 对象,服务器会读取一行数据并发送响应,然后立即回到 accept() 状态,等待下一个连接。这意味着每个客户端只能发送一条消息。为了实现与单个客户端的连续通信,我们需要在接受连接之后,为该连接引入一个内部循环。
修正后的服务器代码示例:
import java.io.*;
import java.net.*;
public class TCPServer {
public static void main(String[] args) throws IOException {
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket(6789);
System.out.println("服务器已启动,等待客户端连接...");
// 外层循环:持续接受新的客户端连接
while (true) {
Socket connectionSocket = welcomeSocket.accept();
System.out.println("新客户端已连接:" + connectionSocket.getInetAddress());
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
// 内层循环:与当前客户端进行持续通信
while (true) {
try {
clientSentence = inFromClient.readLine();
if (clientSentence == null) { // 客户端关闭连接
System.out.println("客户端断开连接:" + connectionSocket.getInetAddress());
break; // 跳出内层循环,等待新客户端
}
System.out.println("收到来自客户端[" + connectionSocket.getInetAddress() + "]的消息: " + clientSentence);
if (clientSentence.equalsIgnoreCase("stop")) {
System.out.println("收到'stop'指令,关闭当前客户端连接。");
outToClient.writeBytes("Server received 'stop'. Connection closing.\n"); // 可选:通知客户端
break; // 收到"stop"指令,跳出内层循环,关闭当前连接
}
capitalizedSentence = clientSentence.toUpperCase() + '\n';
outToClient.writeBytes(capitalizedSentence);
} catch (SocketException e) {
System.out.println("客户端连接异常断开:" + connectionSocket.getInetAddress() + " - " + e.getMessage());
break; // 捕获连接异常,跳出内层循环
} catch (IOException e) {
System.err.println("读取或写入客户端数据时发生错误:" + e.getMessage());
break; // 其他IO错误,跳出内层循环
}
}
// 关闭当前客户端连接的资源
connectionSocket.close();
System.out.println("客户端连接已关闭。");
}
// 注意:如果服务器需要完全终止,则 welcomeSocket 也需要关闭,但通常服务器会一直运行。
// welcomeSocket.close();
}
}服务器端逻辑说明:
客户端需要持续发送用户输入,并接收服务器的响应。关键在于如何检测服务器何时关闭了连接,以便客户端也能优雅地终止。当服务器关闭其输出流时,客户端的 inFromServer.readLine() 方法将返回 null。
立即学习“Java免费学习笔记(深入)”;
修正后的客户端代码示例:
import java.io.*;
import java.net.*;
public class Klient {
public static void main(String[] args) throws UnknownHostException, IOException {
String sentence;
String modifiedSentence;
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = null;
DataOutputStream outToServer = null;
BufferedReader inFromServer = null;
try {
clientSocket = new Socket("127.0.0.1", 6789);
outToServer = new DataOutputStream(clientSocket.getOutputStream());
inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.println("已连接到服务器。输入消息,输入'stop'结束会话。");
// 客户端持续发送和接收数据
while (true) {
System.out.print("请输入消息: ");
sentence = inFromUser.readLine();
if (sentence == null) { // 用户输入流关闭(如Ctrl+D),终止客户端
System.out.println("用户输入流已关闭,客户端即将退出。");
break;
}
outToServer.writeBytes(sentence + '\n'); // 发送数据到服务器
// 接收服务器响应
modifiedSentence = inFromServer.readLine();
if (modifiedSentence == null) { // 服务器关闭了连接
System.out.println("服务器已关闭连接。客户端即将退出。");
break;
}
System.out.println("来自服务器的响应: " + modifiedSentence);
if (sentence.equalsIgnoreCase("stop")) {
System.out.println("已发送'stop'指令,等待服务器响应并关闭连接。");
// 理论上,服务器收到'stop'后会关闭连接,导致下一次readLine返回null
// 这里的break是多余的,但为了清晰性可以保留,或者依赖modifiedSentence == null来退出
break;
}
}
} catch (ConnectException e) {
System.err.println("无法连接到服务器: " + e.getMessage());
} catch (SocketException e) {
System.err.println("网络连接异常: " + e.getMessage());
} catch (IOException e) {
System.err.println("客户端IO操作发生错误: " + e.getMessage());
} finally {
// 确保关闭所有资源
try {
if (inFromUser != null) inFromUser.close();
if (outToServer != null) outToServer.close();
if (inFromServer != null) inFromServer.close();
if (clientSocket != null) clientSocket.close();
System.out.println("客户端资源已释放。");
} catch (IOException e) {
System.err.println("关闭客户端资源时发生错误: " + e.getMessage());
}
}
}
}客户端逻辑说明:
如果服务器不仅要关闭当前客户端连接,而且在收到“stop”指令后要完全终止运行(即不再接受任何新的连接),则需要修改服务器的结构,移除外层 while(true) 循环,并在处理完一个客户端后关闭 ServerSocket。
服务器完全终止代码示例:
import java.io.*;
import java.net.*;
public class SingleClientTerminatingTCPServer {
public static void main(String[] args) throws IOException {
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket = null;
Socket connectionSocket = null;
try {
welcomeSocket = new ServerSocket(6789);
System.out.println("服务器已启动,等待单个客户端连接...");
// 接受一个客户端连接
connectionSocket = welcomeSocket.accept();
System.out.println("客户端已连接:" + connectionSocket.getInetAddress());
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
// 与当前客户端进行持续通信
while (true) {
try {
clientSentence = inFromClient.readLine();
if (clientSentence == null) {
System.out.println("客户端断开连接:" + connectionSocket.getInetAddress());
break;
}
System.out.println("收到来自客户端[" + connectionSocket.getInetAddress() + "]的消息: " + clientSentence);
if (clientSentence.equalsIgnoreCase("stop")) {
System.out.println("收到'stop'指令,服务器即将完全终止。");
outToClient.writeBytes("Server received 'stop'. Server terminating.\n");
break; // 收到"stop"指令,跳出内层循环
}
capitalizedSentence = clientSentence.toUpperCase() + '\n';
outToClient.writeBytes(capitalizedSentence);
} catch (SocketException e) {
System.out.println("客户端连接异常断开:" + connectionSocket.getInetAddress() + " - " + e.getMessage());
break;
} catch (IOException e) {
System.err.println("读取或写入客户端数据时发生错误:" + e.getMessage());
break;
}
}
} catch (IOException e) {
System.err.println("服务器启动或运行过程中发生错误: " + e.getMessage());
} finally {
// 确保关闭所有资源
try {
if (connectionSocket != null) connectionSocket.close();
if (welcomeSocket != null) welcomeSocket.close();
System.out.println("服务器资源已释放,服务器已关闭。");
} catch (IOException e) {
System.err.println("关闭服务器资源时发生错误: " + e.getMessage());
}
}
}
}以上就是Java TCP通信:实现连续数据传输与“停止”指令控制的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号