Java网络编程:从套接字到NIO与WebSockets

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么Java网络编程是一种超能力?



想象一下:你正在编写代码,突然你的程序开始与地球另一端另一个程序通信。它发送请求、接收响应、同步数据——这一切都在毫秒内完成。这不是魔法,这是Java网络编程。如果你想创建的不只是本地工具,而是真正的分布式系统、聊天应用、在线游戏或REST服务——网络编程必不可少。



Java为此提供了强大的工具集:从经典的Socket和ServerSocket,到高性能的Java NIO(非阻塞I/O)以及现代的WebSockets。在本文中,我们将探讨这三种方法,编写实际代码,并理解如何为你的任务选择正确的工具。开始吧!



1. 经典套接字:快速搭建TCP聊天应用



我们从基础开始。Java中的套接字是进入TCP/IP世界的入口。服务器创建ServerSocket,监听端口,接受连接。客户端创建Socket并连接到服务器。这就像一加一那么简单。



编写一个简单的回显服务器



服务器接收来自客户端的消息并将其发送回去(回显)。代码虽然简洁,但展示了全部要点:



import java.io.*;import java.net.*;

public class EchoServer { public static void main(String[] args) { try (ServerSocket serverSocket = new ServerSocket(12345)) { System.out.println("服务器已启动,端口12345..."); Socket clientSocket = serverSocket.accept(); // 阻塞直到连接 System.out.println("客户端已连接: " + clientSocket.getInetAddress());

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("收到: " + inputLine); out.println("回显: " + inputLine); if (inputLine.equalsIgnoreCase("exit")) break; } } catch (IOException e) { e.printStackTrace(); } }}


下面是发送消息的客户端:



import java.io.*;import java.net.*;

public class EchoClient { public static void main(String[] args) throws IOException { Socket socket = new Socket("localhost", 12345); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream())); BufferedReader stdIn = new BufferedReader( new InputStreamReader(System.in));

String userInput; System.out.println("请输入消息(输入exit退出):"); while ((userInput = stdIn.readLine()) != null) { out.println(userInput); System.out.println("服务器响应: " + in.readLine()); if (userInput.equalsIgnoreCase("exit")) break; } socket.close(); }}


这里重要的是什么? accept()和readLine()方法会阻塞线程。这意味着当一个客户端在通信时,其他客户端必须等待。解决方案是多线程。



多线程服务器:处理多个客户端



为每个新连接创建一个单独的线程。使用ExecutorService线程池,避免无谓地创建大量线程:



import java.io.*;import java.net.*;import java.util.concurrent.*;

public class MultiThreadedServer { private static final int PORT = 12345; private static final ExecutorService threadPool = Executors.newFixe

博客

书籍推荐