JavaEE 网络编程套接字详解与实战示例

、套接字(Socket)是什么?

套接字是网络通信的“端点”,就像打电话需要手机一样,网络通信需要套接字建立连接。
两种类型

  • TCP套接字:可靠传输(类似打电话,需先拨通)
  • UDP套接字:快速传输(类似发短信,无需确认对方收到)
二、TCP 套接字编程
1. 服务端开发步骤
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(8080)) { // 1. 绑定端口
            System.out.println("服务器启动,等待连接...");
            
            while (true) {
                Socket clientSocket = serverSocket.accept(); // 2. 阻塞等待客户端连接
                System.out.println("客户端连接成功: " + clientSocket.getInetAddress());
                
                // 3. 处理客户端请求(单线程版)
                try (InputStream is = clientSocket.getInputStream();
                     BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                     OutputStream os = clientSocket.getOutputStream();
                     PrintWriter writer = new PrintWriter(os)) {
                    
                    String request = reader.readLine(); // 读取客户端消息
                    System.out.println("收到请求: " + request);
                    
                    // 返回响应
                    writer.println("服务器响应: " + request.toUpperCase());
                    writer.flush(); // 强制发送数据
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

重点解析

  • ServerSocket(8080):绑定端口 8080,类似开通电话线路。
  • accept():阻塞等待客户端连接,返回客户端 Socket 对象。
  • 单线程问题:一次只能处理一个客户端,需优化为多线程(见下文)。
2. 客户端开发步骤
import java.io.*;
import java.net.Socket;

public class TcpClient {
    public static void main(String[] args) {
        try (Socket socket = new Socket("localhost", 8080); // 1. 连接服务器
             PrintWriter writer = new PrintWriter(socket.getOutputStream());
             BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in))) {
            
            System.out.print("输入消息: ");
            String message = consoleReader.readLine();
            
            writer.println(message); // 2. 发送消息
            writer.flush();
            
            String response = reader.readLine(); // 3. 读取响应
            System.out.println("服务器响应: " + response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

重点解析

  • new Socket("IP", 端口):主动连接服务器。
  • flush():确保数据立即发送(缓冲区可能延迟发送)。
3. 多线程优化服务端
// 修改服务端代码中的处理部分
while (true) {
    Socket clientSocket = serverSocket.accept();
    new Thread(() -> {
        try (InputStream is = clientSocket.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(is));
             OutputStream os = clientSocket.getOutputStream();
             PrintWriter writer = new PrintWriter(os)) {
            
            String request = reader.readLine();
            System.out.println("收到请求: " + request);
            writer.println("响应: " + request.toUpperCase());
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }).start();
}

作用:每个客户端连接分配独立线程,支持并发处理。

三、UDP 套接字编程
1. 服务端开发
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UdpServer {
    public static void main(String[] args) {
        try (DatagramSocket socket = new DatagramSocket(8080)) { // 1. 绑定端口
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
            
            while (true) {
                socket.receive(packet); // 2. 接收数据包(阻塞)
                String message = new String(packet.getData(), 0, packet.getLength());
                System.out.println("收到消息: " + message);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
2. 客户端开发
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpClient {
    public static void main(String[] args) {
        try (DatagramSocket socket = new DatagramSocket()) { // 1. 随机端口
            String message = "Hello UDP";
            byte[] data = message.getBytes();
            
            // 2. 构建数据包(目标地址+端口)
            DatagramPacket packet = new DatagramPacket(
                data, 
                data.length, 
                InetAddress.getByName("localhost"), 
                8080
            );
            
            socket.send(packet); // 3. 发送数据包
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

重点解析

  • UDP 无需建立连接,直接发送数据包。
  • DatagramPacket 包含数据和目标地址信息。
四、JavaEE 中的网络编程

虽然 JavaEE 主要面向 Web 应用(如 Servlet/JSP),但底层仍依赖 Socket:

  • HTTP 协议:基于 TCP,Servlet 容器(如 Tomcat)内部使用 Socket 处理请求。
  • WebSocket:全双工通信协议,适用于实时应用(聊天室、股票行情)。

示例:Servlet 处理 HTTP 请求

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        resp.getWriter().println("Hello from Servlet!"); // 通过TCP响应
    }
}
五、核心总结
  1. TCP vs UDP

    • TCP:可靠、面向连接(文件传输、网页)
    • UDP:快速、无连接(视频流、实时游戏)
  2. 关键类

    • TCP:ServerSocket(服务端)、Socket(客户端)
    • UDP:DatagramSocketDatagramPacket
  3. 开发步骤

    • TCP服务端:绑定端口 → 等待连接 → 处理请求
    • TCP客户端:连接服务端 → 发送/接收数据
    • UDP:构建数据包 → 发送/接收
  4. 注意事项

    • 端口冲突:确保端口未被占用(如 8080、3306)
    • 资源释放:使用 try-with-resources 自动关闭流
    • 多线程:TCP 服务端需处理并发连接

你可能感兴趣的:(网络,java,后端,开发语言)