Java ServerSocket类
Java ServerSocket类[编辑 | 编辑源代码]
ServerSocket 类是 Java 网络编程中的核心类之一,用于在服务器端监听客户端的连接请求。它是实现 TCP/IP 协议通信的基础,允许服务器程序等待并接受来自客户端的连接。
概述[编辑 | 编辑源代码]
ServerSocket 类位于 `java.net` 包中,主要功能是:
- 绑定到特定端口监听连接请求
- 接受客户端连接并返回 Socket 对象
- 设置连接超时等参数
一个典型的服务器端工作流程如下: 1. 创建 ServerSocket 实例并绑定到端口 2. 调用 accept() 方法等待客户端连接 3. 接受连接后通过返回的 Socket 对象进行通信 4. 关闭连接
构造函数[编辑 | 编辑源代码]
ServerSocket 提供了多个构造函数:
// 绑定到指定端口,backlog为连接队列长度
ServerSocket(int port, int backlog)
// 绑定到指定端口和本地IP地址
ServerSocket(int port, int backlog, InetAddress bindAddr)
// 不绑定端口,需要后续调用bind()
ServerSocket()
核心方法[编辑 | 编辑源代码]
基本操作[编辑 | 编辑源代码]
// 绑定到指定地址和端口
void bind(SocketAddress endpoint)
// 等待客户端连接,返回Socket对象
Socket accept()
// 关闭ServerSocket
void close()
配置方法[编辑 | 编辑源代码]
// 设置SO_TIMEOUT(毫秒)
void setSoTimeout(int timeout)
// 获取SO_TIMEOUT值
int getSoTimeout()
// 设置SO_REUSEADDR选项
void setReuseAddress(boolean on)
代码示例[编辑 | 编辑源代码]
基础服务器示例[编辑 | 编辑源代码]
import java.net.*;
import java.io.*;
public class SimpleServer {
public static void main(String[] args) throws IOException {
// 在端口8080上创建服务器
try (ServerSocket serverSocket = new ServerSocket(8080)) {
System.out.println("服务器启动,等待连接...");
// 接受客户端连接
Socket clientSocket = serverSocket.accept();
System.out.println("客户端已连接: " +
clientSocket.getInetAddress());
// 获取输入输出流
PrintWriter out = new PrintWriter(
clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
// 通信循环
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("收到: " + inputLine);
out.println("服务器回应: " + inputLine);
}
}
}
}
多线程服务器示例[编辑 | 编辑源代码]
处理多个客户端连接:
import java.net.*;
import java.io.*;
public class MultiThreadedServer {
public static void main(String[] args) throws IOException {
try (ServerSocket serverSocket = new ServerSocket(8080)) {
System.out.println("多线程服务器启动...");
while (true) {
Socket clientSocket = serverSocket.accept();
// 为每个客户端创建新线程
new Thread(new ClientHandler(clientSocket)).start();
}
}
}
}
class ClientHandler implements Runnable {
private final Socket clientSocket;
public ClientHandler(Socket socket) {
this.clientSocket = socket;
}
public void run() {
try (
PrintWriter out = new PrintWriter(
clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()))
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("线程" + Thread.currentThread().getId() +
" 收到: " + inputLine);
out.println("处理结果: " + inputLine.toUpperCase());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
高级特性[编辑 | 编辑源代码]
超时处理[编辑 | 编辑源代码]
ServerSocket 可以设置超时时间,防止 accept() 无限期阻塞:
ServerSocket serverSocket = new ServerSocket(8080);
serverSocket.setSoTimeout(5000); // 5秒超时
try {
Socket clientSocket = serverSocket.accept();
// 处理连接
} catch (SocketTimeoutException e) {
System.out.println("接受连接超时");
}
端口复用[编辑 | 编辑源代码]
使用 SO_REUSEADDR 选项可以快速重启绑定相同端口的服务器:
ServerSocket serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(8080));
实际应用场景[编辑 | 编辑源代码]
案例:在线聊天服务器 ServerSocket 常用于实现聊天服务器,处理多个客户端的消息转发:
实现要点: 1. 主线程接受新连接 2. 为每个客户端创建独立线程 3. 维护客户端列表 4. 实现消息广播功能
性能考虑[编辑 | 编辑源代码]
- 连接队列: backlog 参数控制未处理连接的最大数量
- 线程池: 使用 ExecutorService 替代直接创建线程
- NIO: 高并发场景考虑使用 ServerSocketChannel
计算公式:最大并发连接数 ≈ 线程池大小 × 单个请求处理时间
其中:
- C = 并发能力
- T = 线程池大小
- t = 平均请求处理时间
常见问题[编辑 | 编辑源代码]
Q: 为什么 accept() 会阻塞? A: accept() 是阻塞调用,直到有客户端连接才会返回。可以使用 setSoTimeout() 设置超时。
Q: 如何处理"Address already in use"错误? A: 设置 SO_REUSEADDR 选项或等待 TCP 的 TIME_WAIT 状态结束(通常2-4分钟)。
Q: 服务器如何优雅关闭? A: 在关闭 ServerSocket 前需要处理所有客户端连接,可以使用标志变量控制循环退出。
最佳实践[编辑 | 编辑源代码]
1. 始终在 finally 块中关闭 ServerSocket 2. 使用 try-with-resources 确保资源释放 3. 为生产环境配置适当的 backlog 值(默认50可能不足) 4. 考虑使用线程池管理客户端连接 5. 实现适当的错误处理和日志记录
总结[编辑 | 编辑源代码]
ServerSocket 是 Java 网络编程的基础类,理解其工作原理对于开发服务器应用至关重要。从简单的单线程服务器到复杂的多线程实现,ServerSocket 提供了构建各种网络服务的基础能力。在实际开发中,应结合具体需求选择合适的实现方式,并注意资源管理和性能优化。