# Java网络编程深度解析:Socket通信实现与应用实践
## 网络编程基础与核心概念
Java网络编程建立在TCP/IP协议栈之上,通过抽象的网络API提供跨平台的通信能力。理解网络编程的基础概念是构建可靠网络应用的前提。
```java
// 网络基础工具类
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
public class NetworkUtils {
// 获取本地主机信息
public static void displayLocalHostInfo() {
try {
InetAddress localHost = InetAddress.getLocalHost();
System.out.println("主机名: " + localHost.getHostName());
System.out.println("主机地址: " + localHost.getHostAddress());
System.out.println("Canonical主机名: " + localHost.getCanonicalHostName());
// 检查是否是回环地址
System.out.println("是否回环地址: " + localHost.isLoopbackAddress());
// 检查是否可到达
System.out.println("可达性检查: " + localHost.isReachable(3000));
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取所有网络接口
public static void displayNetworkInterfaces() {
try {
Enumeration<NetworkInterface> interfaces =
NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface ni = interfaces.nextElement();
System.out.println("\n网络接口: " + ni.getName());
System.out.println("显示名称: " + ni.getDisplayName());
System.out.println("是否启用: " + ni.isUp());
System.out.println("是否回环: " + ni.isLoopback());
// 获取接口地址
Enumeration<InetAddress> addresses = ni.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement();
System.out.println(" 地址: " + addr.getHostAddress());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 域名解析
public static void resolveDomain(String domain) {
try {
InetAddress[] addresses = InetAddress.getAllByName(domain);
System.out.println("域名 " + domain + " 解析结果:");
for (InetAddress addr : addresses) {
System.out.println(" IP地址: " + addr.getHostAddress());
System.out.println(" 规范主机名: " + addr.getCanonicalHostName());
}
} catch (Exception e) {
System.out.println("解析域名失败: " + e.getMessage());
}
}
}
```
## Socket编程基础
### TCP Socket实现
```java
// 基础TCP服务器
import java.io.*;
import java.net.*;
public class BasicTCPServer {
private ServerSocket serverSocket;
private int port;
public BasicTCPServer(int port) {
this.port = port;
}
public void start() {
try {
serverSocket = new ServerSocket(port);
System.out.println("服务器启动,监听端口: " + port);
while (true) {
// 接受客户端连接
Socket clientSocket = serverSocket.accept();
System.out.println("客户端连接: " +
clientSocket.getInetAddress().getHostAddress() + ":" +
clientSocket.getPort());
// 为每个客户端创建处理线程
ClientHandler handler = new ClientHandler(clientSocket);
new Thread(handler).start();
}
} catch (IOException e) {
System.err.println("服务器异常: " + e.getMessage());
} finally {
stop();
}
}
public void stop() {
try {
if (serverSocket != null && !serverSocket.isClosed()) {
serverSocket.close();
System.out.println("服务器已关闭");
}
} catch (IOException e) {
System.err.println("关闭服务器时出错: " + e.getMessage());
}
}
// 客户端处理类
private static class ClientHandler implements Runnable {
private Socket clientSocket;
private BufferedReader in;
private PrintWriter out;
public ClientHandler(Socket socket) {
this.clientSocket = socket;
}
@Override
public void run() {
try {
// 创建输入输出流
in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
out = new PrintWriter(
clientSocket.getOutputStream(), true);
String inputLine;
// 读取客户端消息
while ((inputLine = in.readLine()) != null) {
System.out.println("收到消息: " + inputLine);
// 处理消息并回复
String response = processMessage(inputLine);
out.println(response);
if ("exit".equalsIgnoreCase(inputLine)) {
break;
}
}
} catch (IOException e) {
System.err.println("处理客户端时出错: " + e.getMessage());
} finally {
closeConnection();
}
}
private String processMessage(String message) {
// 简单的消息处理逻辑
if (message.startsWith("echo:")) {
return "回显: " + message.substring(5);
} else if (message.startsWith("time")) {
return "服务器时间: " + new java.util.Date();
} else if ("help".equalsIgnoreCase(message)) {
return "支持命令: echo:<消息>, time, help, exit";
} else {
return "收到: " + message;
}
}
private void closeConnection() {
try {
if (in != null) in.close();
if (out != null) out.close();
if (clientSocket != null && !clientSocket.isClosed()) {
clientSocket.close();
System.out.println("客户端连接已关闭");
}
} catch (IOException e) {
System.err.println("关闭连接时出错: " + e.getMessage());
}
}
}
}
// TCP客户端实现
public class TCPClient {
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private BufferedReader consoleReader;
public void connect(String host, int port) {
try {
socket = new Socket(host, port);
System.out.println("已连接到服务器: " + host + ":" + port);
// 初始化流
in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
consoleReader = new BufferedReader(
new InputStreamReader(System.in));
// 启动接收消息线程
new Thread(this::receiveMessages).start();
// 发送消息
sendMessages();
} catch (IOException e) {
System.err.println("连接失败: " + e.getMessage());
} finally {
disconnect();
}
}
private void sendMessages() {
try {
String userInput;
while ((userInput = consoleReader.readLine()) != null) {
out.println(userInput);
if ("exit".equalsIgnoreCase(userInput)) {
break;
}
}
} catch (IOException e) {
System.err.println("发送消息时出错: " + e.getMessage());
}
}
private void receiveMessages() {
try {
String serverResponse;
while ((serverResponse = in.readLine()) != null) {
System.out.println("服务器回复: " + serverResponse);
}
} catch (IOException e) {
System.out.println("连接已断开");
}
}
private void disconnect() {
try {
if (in != null) in.close();
if (out != null) out.close();
if (consoleReader != null) consoleReader.close();
if (socket != null && !socket.isClosed()) {
socket.close();
}
System.out.println("连接已关闭");
} catch (IOException e) {
System.err.println("关闭连接时出错: " + e.getMessage());
}
}
public static void main(String[] args) {
TCPClient client = new TCPClient();
client.connect("localhost", 8080);
}
}
```
### UDP Socket实现
```java
// UDP服务器
import java.io.*;
import java.net.*;
public class UDPServer {
private DatagramSocket socket;
private int port;
private boolean running;
public UDPServer(int port) {
this.port = port;
}
public void start() {
try {
socket = new DatagramSocket(port);
System.out.println("UDP服务器启动,监听端口: " + port);
running = true;
// 接收缓冲区
byte[] buffer = new byte[1024];
while (running) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// 接收数据包
socket.receive(packet);
// 处理数据包
processPacket(packet);
}
} catch (IOException e) {
System.err.println("服务器异常: " + e.getMessage());
} finally {
stop();
}
}
private void processPacket(DatagramPacket packet) {
try {
String received = new String(
packet.getData(), 0, packet.getLength(), "UTF-8");
InetAddress clientAddress = packet.getAddress();
int clientPort = packet.getPort();
System.out.println("收到来自 " + clientAddress.getHostAddress() +
":" + clientPort + " 的消息: " + received);
// 处理消息
String response = "UDP响应: " + received.toUpperCase();
byte[] responseData = response.getBytes("UTF-8");
// 发送响应
DatagramPacket responsePacket = new DatagramPacket(
responseData, responseData.length, clientAddress, clientPort);
socket.send(responsePacket);
} catch (IOException e) {
System.err.println("处理数据包时出错: " + e.getMessage());
}
}
public void stop() {
running = false;
if (socket != null && !socket.isClosed()) {
socket.close();
System.out.println("UDP服务器已关闭");
}
}
}
// UDP客户端
public class UDPClient {
private DatagramSocket socket;
private InetAddress serverAddress;
private int serverPort;
public UDPClient(String host, int port) {
try {
socket = new DatagramSocket(); // 随机端口
serverAddress = InetAddress.getByName(host);
serverPort = port;
System.out.println("UDP客户端启动,本地端口: " + socket.getLocalPort());
} catch (IOException e) {
System.err.println("初始化客户端失败: " + e.getMessage());
}
}
public void sendMessage(String message) {
try {
byte[] sendData = message.getBytes("UTF-8");
DatagramPacket sendPacket = new DatagramPacket(
sendData, sendData.length, serverAddress, serverPort);
// 发送消息
socket.send(sendPacket);
System.out.println("已发送消息: " + message);
// 接收响应
receiveResponse();
} catch (IOException e) {
System.err.println("发送消息时出错: " + e.getMessage());
}
}
private void receiveResponse() {
try {
byte[] buffer = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);
// 设置超时时间
socket.setSoTimeout(5000);
socket.receive(receivePacket);
String response = new String(
receivePacket.getData(), 0, receivePacket.getLength(), "UTF-8");
System.out.println("收到服务器响应: " + response);
} catch (SocketTimeoutException e) {
System.out.println("接收响应超时");
} catch (IOException e) {
System.err.println("接收响应时出错: " + e.getMessage());
}
}
public void close() {
if (socket != null && !socket.isClosed()) {
socket.close();
System.out.println("UDP客户端已关闭");
}
}
public static void main(String[] args) {
UDPClient client = new UDPClient("localhost", 9090);
client.sendMessage("Hello UDP Server!");
client.close();
}
}
```
## 高级Socket编程技术
### 非阻塞IO与NIO
```java
// 使用NIO实现非阻塞服务器
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
public class NIOServer {
private Selector selector;
private ServerSocketChannel serverChannel;
private int port;
public NIOServer(int port) {
this.port = port;
}
public void start() {
try {
// 打开选择器
selector = Selector.open();
// 打开服务器通道
serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false); // 非阻塞模式
// 绑定端口
ServerSocket serverSocket = serverChannel.socket();
serverSocket.bind(new InetSocketAddress(port));
// 注册接受连接事件
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("NIO服务器启动,监听端口: " + port);
// 事件循环
while (true) {
// 等待事件发生
int readyChannels = selector.select();
if (readyChannels == 0) continue;
// 处理就绪的键
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
keyIterator.remove();
try {
if (key.isAcceptable()) {
acceptConnection(key);
} else if (key.isReadable()) {
readData(key);
} else if (key.isWritable()) {
writeData(key);
}
} catch (IOException e) {
key.cancel();
if (key.channel() != null) {
key.channel().close();
}
System.err.println("处理通道时出错: " + e.getMessage());
}
}
}
} catch (IOException e) {
System.err.println("服务器异常: " + e.getMessage());
} finally {
stop();
}
}
private void acceptConnection(SelectionKey key) throws IOException {
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
SocketChannel clientChannel = serverChannel.accept();
if (clientChannel != null) {
clientChannel.configureBlocking(false);
// 注册读事件
clientChannel.register(selector, SelectionKey.OP_READ);
System.out.println("接受客户端连接: " +
clientChannel.socket().getRemoteSocketAddress());
}
}
private void readData(SelectionKey key) throws IOException {
SocketChannel clientChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = clientChannel.read(buffer);
if (bytesRead == -1) {
// 连接关闭
System.out.println("客户端断开连接: " +
clientChannel.socket().getRemoteSocketAddress());
clientChannel.close();
key.cancel();
return;
}
if (bytesRead > 0) {
buffer.flip();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
String message = new String(data, "UTF-8");
System.out.println("收到消息: " + message);
// 注册写事件以发送响应
clientChannel.register(selector, SelectionKey.OP_WRITE, message);
}
}
private void writeData(SelectionKey key) throws IOException {
SocketChannel clientChannel = (SocketChannel) key.channel();
String response = (String) key.attachment();
if (response != null) {
ByteBuffer buffer = ByteBuffer.wrap(
("服务器响应: " + response).getBytes("UTF-8"));
while (buffer.hasRemaining()) {
clientChannel.write(buffer);
}
// 重新注册读事件
clientChannel.register(selector, SelectionKey.OP_READ);
<"eb.jsnjz.cn"><"fb.csxthr.com"><"gb.zhaiLimao.com">
}
}
public void stop() {
try {
if (selector != null) selector.close();
if (serverChannel != null) serverChannel.close();
System.out.println("NIO服务器已关闭");
} catch (IOException e) {
System.err.println("关闭服务器时出错: " + e.getMessage());
}
}
}
```
### 线程池优化服务器
```java
// 线程池优化的TCP服务器
import java.io.*;
import java.net.*;
import java.util.concurrent.*;
public class ThreadPoolServer {
private ServerSocket serverSocket;
private ExecutorService threadPool;
private int port;
private int poolSize;
public ThreadPoolServer(int port, int poolSize) {
this.port = port;
this.poolSize = poolSize;
}
public void start() {
try {
serverSocket = new ServerSocket(port);
threadPool = Executors.newFixedThreadPool(poolSize);
System.out.println("线程池服务器启动,监听端口: " + port +
",线程池大小: " + poolSize);
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("接受客户端连接: " +
clientSocket.getRemoteSocketAddress());
// 提交任务到线程池
threadPool.submit(new ClientTask(clientSocket));
}
} catch (IOException e) {
System.err.println("服务器异常: " + e.getMessage());
} finally {
stop();
}
}
private static class ClientTask implements Runnable {
private Socket clientSocket;
public ClientTask(Socket socket) {
this.clientSocket = socket;
}
@Override
public void run() {
try (
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(
clientSocket.getOutputStream(), true)
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("线程 " + Thread.currentThread().getName() +
" 收到: " + inputLine);
// 处理请求
String response = handleRequest(inputLine);
out.println(response);
if ("exit".equalsIgnoreCase(inputLine)) {
break;
}
}
} catch (IOException e) {
System.err.println("处理客户端时出错: " + e.getMessage());
} finally {
try {
if (clientSocket != null && !clientSocket.isClosed()) {
clientSocket.close();
}
} catch (IOException e) {
System.err.println("关闭socket时出错: " + e.getMessage());
}
}
}
private String handleRequest(String request) {
// 模拟耗时操作
try {
Thread.sleep(100); // 100ms处理时间
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "处理结果: " + request.toUpperCase();
}
}
public void stop() {
try {
if (serverSocket != null && !serverSocket.isClosed()) {
serverSocket.close();
}
if (threadPool != null) {
threadPool.shutdown();
if (!threadPool.awaitTermination(5, TimeUnit.SECONDS)) {
threadPool.shutdownNow();
}
}
System.out.println("服务器已关闭");
} catch (Exception e) {
System.err.println("关闭服务器时出错: " + e.getMessage());
}
}
}
```
## 实际应用案例
### 文件传输服务器
```java
// 文件传输服务器
import java.io.*;
import java.net.*;
public class FileTransferServer {
private ServerSocket serverSocket;
private int port;
public FileTransferServer(int port) {
this.port = port;
}
public void start() {
try {
serverSocket = new ServerSocket(port);
System.out.println("文件传输服务器启动,监听端口: " + port);
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("客户端连接: " +
clientSocket.getRemoteSocketAddress());
// 为每个客户端创建处理线程
new Thread(new FileHandler(clientSocket)).start();
}
} catch (IOException e) {
System.err.println("服务器异常: " + e.getMessage());
} finally {
stop();
}
}
private static class FileHandler implements Runnable {
private Socket clientSocket;
private DataInputStream dataIn;
private DataOutputStream dataOut;
public FileHandler(Socket socket) {
this.clientSocket = socket;
}
@Override
public void run() {
try {
dataIn = new DataInputStream(clientSocket.getInputStream());
dataOut = new DataOutputStream(clientSocket.getOutputStream());
// 接收命令
String command = dataIn.readUTF();
if ("UPLOAD".equals(command)) {
receiveFile();
} else if ("DOWNLOAD".equals(command)) {
sendFile();
} else if ("LIST".equals(command)) {
listFiles();
} else {
dataOut.writeUTF("未知命令: " + command);
}
} catch (IOException e) {
System.err.println("文件传输错误: " + e.getMessage());
} finally {
closeConnection();
}
}
private void receiveFile() throws IOException {
// 读取文件名和大小
String fileName = dataIn.readUTF();
long fileSize = dataIn.readLong();
System.out.println("开始接收文件: " + fileName + " (" + fileSize + " bytes)");
// 创建文件输出流
FileOutputStream fileOut = new FileOutputStream("uploads/" + fileName);
byte[] buffer = new byte[4096];
long totalRead = 0;
int read;
// 接收文件数据
while (totalRead < fileSize &&
(read = dataIn.read(buffer)) > 0) {
fileOut.write(buffer, 0, read);
totalRead += read;
// 发送进度(可选)
if (totalRead % (1024 * 1024) == 0) { // 每1MB报告一次
int progress = (int) ((totalRead * 100) / fileSize);
System.out.println("接收进度: " + progress + "%");
}
}
fileOut.close();
System.out.println("文件接收完成: " + fileName);
dataOut.writeUTF("文件上传成功");
}
private void sendFile() throws IOException {
// 读取请求的文件名
String fileName = dataIn.readUTF();
File file = new File("uploads/" + fileName);
if (!file.exists() || !file.isFile()) {
dataOut.writeUTF("文件不存在");
return;
}
// 发送文件信息和数据
dataOut.writeUTF("OK");
dataOut.writeLong(file.length());
FileInputStream fileIn = new FileInputStream(file);
byte[] buffer = new byte[4096];
int read;
while ((read = fileIn.read(buffer)) > 0) {
dataOut.write(buffer, 0, read);
}
fileIn.close();
System.out.println("文件发送完成: " + fileName);
}
private void listFiles() throws IOException {
File uploadDir = new File("uploads");
File[] files = uploadDir.listFiles();
if (files == null || files.length == 0) {
dataOut.writeUTF("无文件");
return;
}
StringBuilder fileList = new StringBuilder();
for (File file : files) {
if (file.isFile()) {
fileList.append(file.getName())
.append(" (")
.append(file.length())
.append(" bytes)\n");
}
}
dataOut.writeUTF(fileList.toString());
}
private void closeConnection() {
try {
if (dataIn != null) dataIn.close();
if (dataOut != null) dataOut.close();
if (clientSocket != null && !clientSocket.isClosed()) {
clientSocket.close();
}
} catch (IOException e) {
System.err.println("关闭连接时出错: " + e.getMessage());
}
}
}
public void stop() {
try {
if (serverSocket != null && !serverSocket.isClosed()) {
serverSocket.close();
}
System.out.println("文件传输服务器已关闭");
} catch (IOException e) {
System.err.println("关闭服务器时出错: " + e.getMessage());
}
}
}
// 文件传输客户端
public class FileTransferClient {
private Socket socket;
private DataInputStream dataIn;
private DataOutputStream dataOut;
public void connect(String host, int port) throws IOException {
socket = new Socket(host, port);
dataIn = new DataInputStream(socket.getInputStream());
dataOut = new DataOutputStream(socket.getOutputStream());
System.out.println("已连接到文件服务器");
}
public void uploadFile(String filePath) throws IOException {
File file = new File(filePath);
if (!file.exists() || !file.isFile()) {
System.out.println("文件不存在: " + filePath);
return;
}
// 发送上传命令
dataOut.writeUTF("UPLOAD");
// 发送文件信息
dataOut.writeUTF(file.getName());
dataOut.writeLong(file.length());
// 发送文件数据
FileInputStream fileIn = new FileInputStream(file);
byte[] buffer = new byte[4096];
int read;
while ((read = fileIn.read(buffer)) > 0) {
dataOut.write(buffer, 0, read);
}
fileIn.close();
// 接收服务器响应
String response = dataIn.readUTF();
System.out.println("服务器响应: " + response);
}
public void downloadFile(String fileName, String savePath) throws IOException {
// 发送下载命令
dataOut.writeUTF("DOWNLOAD");
dataOut.writeUTF(fileName);
// 接收响应
String response = dataIn.readUTF();
if (!"OK".equals(response)) {
System.out.println("下载失败: " + response);
return;
}
// 接收文件大小
long fileSize = dataIn.readLong();
System.out.println("开始下载文件: " + fileName + " (" + fileSize + " bytes)");
// 接收文件数据
FileOutputStream fileOut = new FileOutputStream(savePath + "/" + fileName);
byte[] buffer = new byte[4096];
long totalRead = 0;
int read;
while (totalRead < fileSize && (read = dataIn.read(buffer)) > 0) {
fileOut.write(buffer, 0, read);
totalRead += read;
}
fileOut.close();
System.out.println("文件下载完成: " + fileName);
}
public void listFiles() throws IOException {
dataOut.writeUTF("LIST");
String fileList = dataIn.readUTF();
System.out.println("服务器文件列表:\n" + fileList);
}
public void disconnect() {
try {
if (dataIn != null) dataIn.close();
if (dataOut != null) dataOut.close();
if (socket != null && !socket.isClosed()) {
socket.close();
}
System.out.println("连接已关闭");
} catch (IOException e) {
System.err.println("关闭连接时出错: " + e.getMessage());
<"hb.yunruiwater.cn"><"ib.sxyicheng.cn"><"jb.jsnjz.cn">
}
}
}
```
### 聊天服务器实现
```java
// 多用户聊天服务器
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
public class ChatServer {
private ServerSocket serverSocket;
private ExecutorService threadPool;
private Map<String, ClientHandler> clients;
private int port;
public ChatServer(int port) {
this.port = port;
this.clients = new ConcurrentHashMap<>();
}
public void start() {
try {
serverSocket = new ServerSocket(port);
threadPool = Executors.newCachedThreadPool();
System.out.println("聊天服务器启动,监听端口: " + port);
while (true) {
Socket clientSocket = serverSocket.accept();
ClientHandler handler = new ClientHandler(clientSocket);
threadPool.submit(handler);
}
} catch (IOException e) {
System.err.println("服务器异常: " + e.getMessage());
} finally {
stop();
}
}
private class ClientHandler implements Runnable {
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private String username;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// 用户注册
out.println("请输入用户名:");
username = in.readLine();
// 检查用户名是否已存在
synchronized (clients) {
if (clients.containsKey(username)) {
out.println("用户名已存在,请重新连接");
return;
}
clients.put(username, this);
}
// 广播用户加入
broadcast(username + " 加入了聊天室");
System.out.println(username + " 连接: " + socket.getRemoteSocketAddress());
out.println("欢迎 " + username + "! 输入 /help 查看命令");
// 处理消息
String message;
while ((message = in.readLine()) != null) {
if (message.startsWith("/")) {
handleCommand(message);
} else {
broadcast(username + ": " + message);
}
}
} catch (IOException e) {
System.err.println("客户端 " + username + " 连接异常: " + e.getMessage());
} finally {
disconnect();
}
}
private void handleCommand(String command) throws IOException {
if (command.equals("/help")) {
out.println("可用命令:");
out.println("/help - 显示帮助");
out.println("/list - 列出在线用户");
out.println("/whisper <用户名> <消息> - 私聊");
out.println("/exit - 退出聊天室");
} else if (command.equals("/list")) {
out.println("在线用户 (" + clients.size() + "):");
for (String user : clients.keySet()) {
out.println(" " + user);
}
} else if (command.startsWith("/whisper ")) {
String[] parts = command.split(" ", 3);
if (parts.length == 3) {
String target = parts[1];
String msg = parts[2];
ClientHandler targetHandler = clients.get(target);
if (targetHandler != null) {
targetHandler.out.println("【私聊】" + username + ": " + msg);
out.println("【私聊】发送给 " + target + ": " + msg);
} else {
out.println("用户 " + target + " 不在线");
}
} else {
out.println("用法: /whisper <用户名> <消息>");
}
} else if (command.equals("/exit")) {
throw new IOException("用户退出");
} else {
out.println("未知命令: " + command);
}
}
private void disconnect() {
if (username != null) {
clients.remove(username);
broadcast(username + " 离开了聊天室");
System.out.println(username + " 断开连接");
}
try {
if (in != null) in.close();
if (out != null) out.close();
if (socket != null && !socket.isClosed()) {
socket.close();
}
} catch (IOException e) {
System.err.println("关闭连接时出错: " + e.getMessage());
}
}
private void broadcast(String message) {
System.out.println("[广播] " + message);
for (ClientHandler client : clients.values()) {
client.out.println(message);
}
}
}
public void stop() {
try {
if (serverSocket != null && !serverSocket.isClosed()) {
serverSocket.close();
}
if (threadPool != null) {
threadPool.shutdown();
if (!threadPool.awaitTermination(5, TimeUnit.SECONDS)) {
threadPool.shutdownNow();
}
}
// 断开所有客户端
for (ClientHandler client : clients.values()) {
client.out.println("服务器关闭");
client.socket.close();
}
clients.clear();
System.out.println("聊天服务器已关闭");
} catch (Exception e) {
System.err.println("关闭服务器时出错: " + e.getMessage());
}
}
}
```
## 网络编程最佳实践
### 连接管理与异常处理
```java
// 健壮的网络客户端
import java.io.*;
import java.net.*;
import java.util.concurrent.atomic.AtomicInteger;
public class RobustClient {
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private String host;
private int port;
private AtomicInteger retryCount = new AtomicInteger(0);
private static final int MAX_RETRIES = 3;
private static final long RETRY_DELAY = 2000; // 2秒
public RobustClient(String host, int port) {
this.host = host;
this.port = port;
}
public boolean connectWithRetry() {
while (retryCount.get() < MAX_RETRIES) {
try {
socket = new Socket();
// 设置连接超时
socket.connect(new InetSocketAddress(host, port), 5000);
// 设置读写超时
socket.setSoTimeout(10000);
// 启用TCP保活机制
socket.setKeepAlive(true);
// 初始化流
in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("成功连接到服务器: " + host + ":" + port);
retryCount.set(0);
return true;
} catch (IOException e) {
retryCount.incrementAndGet();
System.err.println("连接失败 (" + retryCount.get() +
"/" + MAX_RETRIES + "): " + e.getMessage());
if (retryCount.get() < MAX_RETRIES) {
try {
System.out.println("等待 " + RETRY_DELAY/1000 +
" 秒后重试...");
Thread.sleep(RETRY_DELAY);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
return false;
}
}
}
}
return false;
}
public String sendRequest(String request) {
try {
out.println(request);
return in.readLine();
} catch (SocketTimeoutException e) {
System.err.println("请求超时: " + request);
return null;
} catch (IOException e) {
System.err.println("发送请求时出错: " + e.getMessage());
// 尝试重新连接
if (connectWithRetry()) {
return sendRequest(request); // 重试请求
}
return null;
}
}
public void disconnect() {
try {
if (in != null) in.close();
if (out != null) out.close();
if (socket != null && !socket.isClosed()) {
socket.close();
}
System.out.println("连接已关闭");
} catch (IOException e) {
System.err.println("关闭连接时出错: " + e.getMessage());
}
}
// 监控连接状态
public boolean isConnected() {
return socket != null &&
socket.isConnected() &&
!socket.isClosed() &&
!socket.isInputShutdown() &&
!socket.isOutputShutdown();
}
// 心跳检测
public boolean heartbeat() {
try {
String response = sendRequest("PING");
return "PONG".equals(response);
} catch (Exception e) {
return false;
}
}
}
```
Java网络编程提供了强大而灵活的工具集,从基础的Socket通信到高级的NIO非阻塞IO,能够满足各种网络应用需求。通过合理的架构设计、线程池管理、异常处理和连接优化,可以构建出稳定高效的网络应用程序。掌握这些核心技术,能够为开发分布式系统、实时通信应用等复杂网络场景奠定坚实基础。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/19545/viewspace-3108958/ ,如需转载,请注明出处,否则将追究法律责任。