| 特性 | TCP | UDP |
|---|---|---|
| 连接模式 | 面向连接(三次握手/四次挥手) | 无连接 |
| 可靠性 | 有序、无丢失、无重复(重传+序列号+ACK) | 尽力而为,可能丢包/乱序/重复 |
| 流量控制 | 滑动窗口 | 无 |
| 适用场景 | HTTP、RPC、数据库、即时通讯核心链路 | 视频流、DNS、广播、可容忍丢包的实时场景 |
public class TcpServer {
private static final int PORT = 8080;
private static final ExecutorService POOL = Executors.newCachedThreadPool();
public static void main(String[] args) throws IOException {
try (ServerSocket server = new ServerSocket(PORT)) {
System.out.println("Server listening on " + PORT);
while (true) {
Socket client = server.accept();
POOL.submit(() -> handleClient(client));
}
}
}
private static void handleClient(Socket socket) {
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true)) {
String msg;
while ((msg = in.readLine()) != null) {
System.out.println("Received: " + msg);
out.println("Echo: " + msg);
if ("bye".equalsIgnoreCase(msg)) break;
}
} catch (IOException e) {
log.error("Client error", e);
} finally {
try { socket.close(); } catch (IOException ignored) {}
}
}
}
public class TcpClient {
public static void main(String[] args) throws IOException {
String host = "127.0.0.1";
int port = 8080;
try (Socket socket = new Socket(host, port);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true);
BufferedReader console = new BufferedReader(new InputStreamReader(System.in))) {
String line;
while ((line = console.readLine()) != null) {
out.println(line);
System.out.println("Server: " + in.readLine());
if ("bye".equalsIgnoreCase(line)) break;
}
}
}
}
HttpClient 4.5+ 封装了连接池、重试、拦截器等企业级特性,适合 REST/RPC 场景。以下示例演示客户端发送序列化对象,服务端反序列化处理并返回结果。
public class RequestPayload implements Serializable {
private String command;
private Map params;
// getter/setter/构造器
}
public class ResponsePayload implements Serializable {
private int code;
private String message;
private Object data;
// getter/setter/构造器
}
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(new PoolingHttpClientConnectionManager())
.evictIdleConnections(30, TimeUnit.SECONDS)
.build();
HttpPost post = new HttpPost("https://localhost:8080/api/process");
post.setHeader("Content-Type", "application/x-java-serialized-object");
RequestPayload req = new RequestPayload("QUERY", Map.of("id", 1001));
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(req);
post.setEntity(new ByteArrayEntity(bos.toByteArray()));
try (CloseableHttpResponse resp = client.execute(post);
ObjectInputStream ois = new ObjectInputStream(resp.getEntity().getContent())) {
ResponsePayload result = (ResponsePayload) ois.readObject();
System.out.println("Result: " + result.getData());
}
}
@WebServlet("/api/process")
public class ProcessServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("application/x-java-serialized-object");
try (ObjectInputStream ois = new ObjectInputStream(req.getInputStream());
ObjectOutputStream oos = new ObjectOutputStream(resp.getOutputStream())) {
RequestPayload payload = (RequestPayload) ois.readObject();
// 业务处理...
ResponsePayload result = new ResponsePayload(200, "OK", "Processed: " + payload.getCommand());
oos.writeObject(result);
} catch (ClassNotFoundException | IOException e) {
log.error("Deserialize/process failed", e);
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
}
}
BufferedReader br)不应声明为 static,否则多客户端并发会数据错乱。readLine() 返回 null 表示流结束,而非空字符串,直接 if (br.readLine().equals(...)) 会 NPE。connect 按钮事件中 new Socket() 会阻塞 UI 线程,必须放入后台线程(SwingWorker/CompletableFuture),否则界面冻结。private static final long serialVersionUID,防止版本不一致导致 InvalidClassException。