1. Java 网络编程概述
Java 网络编程是通过 java.net
包实现的,Socket
类是用来进行客户端与服务器通信的主要类。服务器端通过 ServerSocket 类来监听客户端的请求,客户端则通过 Socket 类来连接服务器。
2. TCP 网络编程示例
在 TCP 通信中,数据传输是可靠的,确保了数据的顺序和完整性。以下是一个简单的客户端和服务器应用,其中服务器端监听指定端口,客户端向服务器发送消息并接收响应。
2.1 TCP 服务器端
import java.io.*; import java.net.*; public class TCPServer { public static void main(String[] args) { try { // 创建ServerSocket对象,监听端口12345 ServerSocket serverSocket = new ServerSocket(12345); System.out.println("Server is listening on port 12345..."); while (true) { // 等待客户端连接 Socket clientSocket = serverSocket.accept(); System.out.println("New client connected: " + clientSocket.getInetAddress()); // 创建线程来处理客户端请求 Thread clientThread = new Thread(new ClientHandler(clientSocket)); clientThread.start(); } } catch (IOException e) { e.printStackTrace(); } } } class ClientHandler implements Runnable { private 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 message = in.readLine(); System.out.println("Received from client: " + message); // 发送响应给客户端 out.println("Hello from server!"); // 关闭连接 clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }
2.2 TCP 客户端
import java.io.*; import java.net.*; public class TCPClient { public static void main(String[] args) { try { // 创建Socket对象连接到服务器 Socket socket = new Socket("localhost", 12345); System.out.println("Connected to the server"); // 获取输入输出流 PrintWriter out = new PrintWriter(socket.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 向服务器发送消息 out.println("Hello from client!"); // 接收服务器响应 String response = in.readLine(); System.out.println("Received from server: " + response); // 关闭连接 socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
运行步骤:
- 先启动
TCPServer
,它将监听端口 12345。 - 然后启动
TCPClient
,它将连接到服务器并发送消息。
输出示例:
-
服务器端:
Server is listening on port 12345... New client connected: /127.0.0.1 Received from client: Hello from client!
-
客户端:
Connected to the server Received from server: Hello from server!
3. UDP 网络编程示例
UDP 是一种无连接、不保证可靠性的协议,适用于实时性要求高,但对数据丢失不敏感的场景(如视频流、在线游戏等)。
3.1 UDP 服务器端
import java.net.*; public class UDPServer { public static void main(String[] args) { try { // 创建UDP服务器端套接字 DatagramSocket serverSocket = new DatagramSocket(12345); System.out.println("UDP Server is listening on port 12345..."); byte[] receiveData = new byte[1024]; while (true) { // 创建数据报包来接收客户端消息 DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); serverSocket.receive(receivePacket); // 获取客户端地址和数据 String clientMessage = new String(receivePacket.getData(), 0, receivePacket.getLength()); System.out.println("Received from client: " + clientMessage); // 发送响应给客户端 InetAddress clientAddress = receivePacket.getAddress(); int clientPort = receivePacket.getPort(); String responseMessage = "Hello from UDP server!"; DatagramPacket sendPacket = new DatagramPacket(responseMessage.getBytes(), responseMessage.length(), clientAddress, clientPort); serverSocket.send(sendPacket); } } catch (Exception e) { e.printStackTrace(); } } }
3.2 UDP 客户端
import java.net.*;
public class UDPClient {
public static void main(String[] args) {
try {
// 创建UDP客户端套接字
DatagramSocket clientSocket = new DatagramSocket();
InetAddress serverAddress = InetAddress.getByName("localhost");// 发送消息给服务器
String message = "Hello from UDP client!";
DatagramPacket sendPacket = new DatagramPacket(message.getBytes(), message.length(), serverAddress, 12345);
clientSocket.send(sendPacket);// 接收服务器的响应
byte[] receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);// 显示服务器响应
String response = new String(receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("Received from server: " + response);// 关闭客户端套接字
clientSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行步骤:
- 先启动
UDPServer
,它将监听端口 12345。 - 然后启动
UDPClient
,它将向服务器发送消息并接收响应。
输出示例:
-
服务器端:
UDP Server is listening on port 12345... Received from client: Hello from UDP client!
-
客户端:
Received from server: Hello from UDP server!
4. 多线程和线程池示例
为了处理多个客户端的连接,可以使用 多线程 来为每个客户端创建独立的处理线程。此外,使用 线程池 可以有效地管理线程,提高服务器的性能。
4.1 使用线程池管理客户端请求
(1)线程池版的 TCP 服务器:
import java.io.*; import java.net.*; import java.util.concurrent.*; public class ThreadPoolTCPServer { private static final int PORT = 12345; public static void main(String[] args) { try { // 创建线程池 ExecutorService threadPool = Executors.newFixedThreadPool(10); // 创建ServerSocket并监听端口 ServerSocket serverSocket = new ServerSocket(PORT); System.out.println("Server is listening on port " + PORT); while (true) { // 接受客户端连接 Socket clientSocket = serverSocket.accept(); System.out.println("New client connected: " + clientSocket.getInetAddress()); // 将客户端连接交给线程池处理 threadPool.submit(new ClientHandler(clientSocket)); } } catch (IOException e) { e.printStackTrace(); } } static class ClientHandler implements Runnable { private 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 message = in.readLine(); System.out.println("Received from client: " + message); out.println("Hello from server!"); // 关闭连接 clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
多线程和线程池的优势:
- 使用 线程池 可以避免频繁创建和销毁线程,从而提升性能。
- 每个客户端连接都会分配一个线程,线程池确保了线程的复用。
喜欢这期内容的话,别忘了点个赞,关注博主,这样就不会错过任何更新啦!还有,收藏一下,方便以后回顾哦!