【HeadFirst系列之HeadFirstJava】第15天之🚀 探索 Java 网络与多线程:从 Socket 通信到高性能服务器实战!

Scroll Down

深入理解 Java 网络编程:基于《Head First Java》第 15 章解析

网络通信 是现代应用程序不可或缺的一部分,而 Java 作为一门强大的面向对象编程语言,提供了完整的 网络 API,让开发者可以轻松编写 基于 TCP/IP 协议的网络应用

本文基于《Head First Java》第 15 章 “网络与线程——网络联机”,带你深入理解 Java 网络通信,并通过代码示例,帮助你掌握 Socket服务器/客户端模型 以及 多线程处理并发请求

15-网络与线程-网络联机-前言

📌 1. Java 网络通信基础

Java 提供了 java.net 包来支持 TCP/IPUDP 这两种主流协议。

  • TCP(传输控制协议):面向连接,保证数据有序、完整传输,如 HTTP、FTP。
  • UDP(用户数据报协议):无连接,发送数据不保证到达顺序,如视频直播、在线游戏。

在 Java 中,最常用的类包括:

  • Socket:用于创建客户端连接。
  • ServerSocket:用于创建服务器监听。
  • InetAddress:用于表示 IP 地址信息。

📌 2. 使用 Socket 进行网络通信(TCP)

Socket 是 Java 处理 TCP 连接 的核心类,它提供了一种 客户端-服务器 模型,让两个应用程序能够在网络中进行数据交换。

(1)构建服务器

服务器端主要使用 ServerSocket 监听客户端请求,并通过 accept() 方法接受连接:

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

public class SimpleServer {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(5000)) {
            System.out.println("服务器已启动,等待客户端连接...");
            
            while (true) {
                Socket socket = serverSocket.accept();  // 等待客户端连接
                System.out.println("客户端已连接:" + socket.getInetAddress());

                // 读取客户端消息
                BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter output = new PrintWriter(socket.getOutputStream(), true);

                String receivedMessage = input.readLine();
                System.out.println("收到客户端消息:" + receivedMessage);

                // 发送响应
                output.println("服务器收到:" + receivedMessage);

                // 关闭连接
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

(2)构建客户端

客户端使用 Socket 连接到服务器,并发送数据:

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

public class SimpleClient {
    public static void main(String[] args) {
        try (Socket socket = new Socket("localhost", 5000)) {
            PrintWriter output = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            // 发送消息
            output.println("Hello, Server!");

            // 读取服务器响应
            String response = input.readLine();
            System.out.println("服务器回应:" + response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

(3)运行结果

先运行 SimpleServer,然后运行 SimpleClient,可以看到:

服务器已启动,等待客户端连接...
客户端已连接:/127.0.0.1
收到客户端消息:Hello, Server!

客户端输出:

服务器回应:服务器收到:Hello, Server!

📌 总结

  • 服务器创建 ServerSocket 并等待客户端连接。
  • 客户端通过 Socket 连接服务器并发送消息。
  • 服务器通过 accept() 方法接受连接,读取数据并返回响应。

📌 3. 使用多线程处理多个客户端

在实际开发中,服务器需要同时处理多个客户端请求,ServerSocket 默认是 阻塞模式,意味着 每次只能处理一个客户端
为了解决这个问题,我们可以使用 多线程 让每个客户端连接都由一个独立线程处理。

(1)修改服务器支持多线程

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

public class MultiThreadServer {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(5000)) {
            System.out.println("服务器已启动,等待客户端连接...");
            
            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("新客户端连接:" + clientSocket.getInetAddress());

                // 为每个客户端启动新线程
                new ClientHandler(clientSocket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 处理客户端请求的线程
class ClientHandler extends Thread {
    private Socket clientSocket;

    public ClientHandler(Socket socket) {
        this.clientSocket = socket;
    }

    public void run() {
        try (
            BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            PrintWriter output = new PrintWriter(clientSocket.getOutputStream(), true)
        ) {
            String message = input.readLine();
            System.out.println("收到客户端消息:" + message);
            output.println("服务器收到:" + message);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

📌 优化点

  • 每个客户端连接都由一个 ClientHandler 线程处理,防止服务器阻塞。
  • while (true) 监听多个客户端,保证服务器持续运行。

📌 4. UDP 编程(无连接通信)

UDP 适用于 低延迟场景,如游戏、视频等。Java 提供了 DatagramSocketDatagramPacket 处理 UDP 数据。

(1)UDP 服务器

import java.net.*;

public class UDPServer {
    public static void main(String[] args) {
        try (DatagramSocket socket = new DatagramSocket(5000)) {
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

            System.out.println("UDP 服务器启动,等待数据...");
            socket.receive(packet);

            String message = new String(packet.getData(), 0, packet.getLength());
            System.out.println("收到客户端消息:" + message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

(2)UDP 客户端

import java.net.*;

public class UDPClient {
    public static void main(String[] args) {
        try (DatagramSocket socket = new DatagramSocket()) {
            byte[] buffer = "Hello UDP Server!".getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("localhost"), 5000);

            socket.send(packet);
            System.out.println("消息已发送");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

📌 5. 结语

在本章内容中,我们学习了:
Java 网络编程基础(TCP / UDP)
使用 Socket 进行 TCP 通信
多线程服务器处理多个客户端
UDP 服务器与客户端通信

通过这些示例,你可以构建自己的网络聊天程序、远程调用服务、多人在线游戏等应用!🚀