ServerSocket
是 Java 网络编程中的一个核心类,用于实现服务器端的套接字连接。这个类的对象可以绑定到一个特定的端口上,并侦听该端口上的客户端连接请求。当 ServerSocket
接受一个请求时,它会创建一个新的 Socket
对象,通过这个 Socket
,服务器可以与客户端进行通信。
以下是使用 ServerSocket
的一些基本步骤:
- 创建
ServerSocket
实例:int port = 1234; // 服务器将监听的端口号 ServerSocket serverSocket = new ServerSocket(port); ``` 这里创建了一个绑定到端口 1234 的 `ServerSocket` 实例。
- 侦听连接请求:
Socket clientSocket = serverSocket.accept(); ``` ``accept()` 方法是阻塞的,会等待直到一个连接建立。当一个客户端连接时,`accept()` 方法会返回一个新的 `Socket` 对象,用于与客户端通信。
- 处理客户端数据:
InputStream input = clientSocket.getInputStream(); OutputStream output = clientSocket.getOutputStream(); ``` 通过从 `Socket` 对象获取输入和输出流,服务器可以读取客户端发送的数据,并向客户端发送数据。
- 关闭连接:
clientSocket.close(); serverSocket.close(); ``` 在完成数据交换后,应该关闭客户端套接字和服务器套接字以释放资源。
下面是一个简单的 ServerSocket
示例代码,演示了如何创建一个简单的服务器程序,该程序侦听端口 1234 上的连接请求,并为每个连接请求提供服务:
import java.io.*;
import java.net.*;
public class SimpleServer {
public static void main(String[] args) {
int port = 1234;
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
System.out.println("Server is listening on port " + port);
while (true) {
// Wait for a connection
Socket clientSocket = serverSocket.accept();
System.out.println("New client connected");
// Create input and output streams
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
// Read message from the client and echo it back
String clientMessage;
while ((clientMessage = in.readLine()) != null) {
System.out.println("Client says: " + clientMessage);
out.println(clientMessage); // Echo the received message back to the client
}
// Close the connection with the client
clientSocket.close();
System.out.println("Client disconnected");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// Close the server socket
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
注意:
- 这个例子中的服务器是多次迭代的,每次迭代处理一个连接。
- 服务器应该在多线程环境下运行,每个客户端连接由一个单独的线程处理,以提高并发性。
- 服务器和客户端之间的通信应考虑到线程安全和错误处理,以确保资源得到适当管理并且通信是健壮的。
以下是使用
ServerSocket
的不同场景的一些示例:示例 1: 多线程回声服务器
在这个示例中,服务器为每个连接创建一个新的线程,这允许服务器同时处理多个客户端。
import java.io.*; import java.net.*; public class MultiThreadedEchoServer { private static final int PORT = 1234; public static void main(String[] args) { try (ServerSocket serverSocket = new ServerSocket(PORT)) { System.out.println("Server started. Listening on Port " + PORT); while (true) { Socket clientSocket = serverSocket.accept(); System.out.println("Client connected from " + clientSocket.getInetAddress().getHostAddress()); Thread handlerThread = new Thread(new ClientHandler(clientSocket)); handlerThread.start(); } } catch (IOException e) { e.printStackTrace(); } } private static class ClientHandler implements Runnable { private final Socket clientSocket; public ClientHandler(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("Server received: " + inputLine); out.println(inputLine); // Echo the message back to the client } } catch (IOException e) { e.printStackTrace(); } finally { try { clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
示例 2: 带有超时设置的服务器
在下面的示例中,我们将演示如何为
ServerSocket
设置连接超时,这样如果没有客户端连接,服务器不会永远阻塞在accept
方法上。import java.io.*; import java.net.*; public class TimeoutServer { public static void main(String[] args) { int port = 1234; try (ServerSocket serverSocket = new ServerSocket(port)) { serverSocket.setSoTimeout(10000); // 设置超时时间为10秒 System.out.println("Server is listening on port " + port); try { Socket clientSocket = serverSocket.accept(); // Handle clientSocket... } catch (SocketTimeoutException e) { System.out.println("No client connected within the timeout period."); } } catch (IOException e) { e.printStackTrace(); } } }
示例 3: 使用 SSL/TLS 的安全服务器
要创建一个使用 SSL/TLS 加密连接的服务器,可以使用
SSLServerSocket
,它是ServerSocket
的子类。import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLSocket; import java.io.*; // 注意:运行此示例需要正确配置的密钥库和信任库。 public class SecureServerExample { public static void main(String[] args) { int port = 1234; SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); try (SSLServerSocket serverSocket = (SSLServerSocket) ssf.createServerSocket(port)) { System.out.println("SSL Server is listening on port " + port); SSLSocket clientSocket = (SSLSocket) serverSocket.accept(); // Handle clientSocket... } catch (IOException e) { e.printStackTrace(); } } }
在使用
SSLServerSocket
之前,需要执行一些额外的设置,比如配置 Java 密钥库(keystore)和信任库(truststore),并设置相关的系统属性,以便 JVM 能够找到并使用这些密钥和证书。这通常涉及到使用keytool
实用程序,这是 JDK 提供的一个管理密钥和证书的工具。请注意,每个示例中的错误处理都很基本。在生产环境中,你需要考虑更健壮的异常处理和资源管理策略。