杰瑞科技汇

Java Socket如何实现服务器与客户端通信?

我会分步进行,从最基础的 TCP Socket 开始,因为它提供了稳定、可靠的连接,然后再介绍更灵活的 UDP Socket

Java Socket如何实现服务器与客户端通信?-图1
(图片来源网络,侵删)

第一部分:TCP Socket 编程 (可靠连接)

TCP (Transmission Control Protocol) 是一种面向连接的、可靠的协议,它就像打电话,必须先拨号(建立连接),双方通话(数据传输),最后挂断(关闭连接),数据在传输过程中有保证,不会丢失、重复或乱序。

核心概念

  1. 服务器端:

    • ServerSocket: 服务器端使用它来监听某个端口,等待客户端的连接请求。
    • accept(): 这是一个阻塞方法,当有客户端连接时,它会返回一个 Socket 对象,服务器端通过这个 Socket 与客户端进行后续的通信。
  2. 客户端:

    • Socket: 客户端使用它来发起对服务器的连接请求。
    • 一旦连接成功,客户端也会得到一个 Socket 对象,用于与服务器通信。
  3. I/O 流:

    Java Socket如何实现服务器与客户端通信?-图2
    (图片来源网络,侵删)
    • 连接建立后,双方都通过 Socket 对象获取输入流和输出流来进行数据的读写。
    • getInputStream(): 获取输入流,用于读取对方发送过来的数据。
    • getOutputStream(): 获取输出流,用于向对方发送数据。

步骤 1:创建 TCP 服务器

服务器的工作流程是:打开一个端口 -> 等待连接 -> 处理通信 -> 关闭连接,这个处理过程通常需要在一个循环中,以便能服务多个客户端。

TCPServer.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
    public static void main(String[] args) {
        int port = 8888; // 服务器监听的端口号
        // 使用 try-with-resources 语句,确保 ServerSocket 和 Socket 在使用后能被自动关闭
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("服务器启动,正在监听端口 " + port + "...");
            // accept() 方法会阻塞,直到有客户端连接
            Socket clientSocket = serverSocket.accept();
            System.out.println("客户端已连接: " + clientSocket.getInetAddress().getHostAddress());
            // 获取客户端的输入流,用于读取客户端发送的数据
            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);
                // 如果客户端发送 "exit",则结束通信
                if ("exit".equalsIgnoreCase(inputLine)) {
                    System.out.println("客户端请求断开连接。");
                    break;
                }
                // 将收到的消息回显给客户端
                String responseMessage = "服务器收到: " + inputLine;
                out.println(responseMessage);
            }
        } catch (IOException e) {
            System.err.println("服务器异常: " + e.getMessage());
            e.printStackTrace();
        }
        System.out.println("服务器已关闭。");
    }
}

步骤 2:创建 TCP 客户端

客户端的工作流程是:创建 Socket 连接服务器 -> 发送数据 -> 接收数据 -> 关闭连接

TCPClient.java

Java Socket如何实现服务器与客户端通信?-图3
(图片来源网络,侵删)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class TCPClient {
    public static void main(String[] args) {
        String hostname = "localhost"; // 或服务器的 IP 地址
        int port = 8888;
        // 使用 try-with-resources 语句,确保 Socket, PrintWriter, BufferedReader 在使用后能被自动关闭
        try (Socket socket = new Socket(hostname, port);
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
             BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             Scanner scanner = new Scanner(System.in)) {
            System.out.println("已连接到服务器 " + hostname + ":" + port);
            System.out.println("请输入消息 (输入 'exit' 退出):");
            // 从控制台读取用户输入
            while (scanner.hasNextLine()) {
                String userInput = scanner.nextLine();
                // 发送消息到服务器
                out.println(userInput);
                // 如果用户输入 "exit",则退出循环
                if ("exit".equalsIgnoreCase(userInput)) {
                    break;
                }
                // 读取服务器返回的响应
                String response = in.readLine();
                if (response != null) {
                    System.out.println("服务器响应: " + response);
                }
            }
        } catch (UnknownHostException e) {
            System.err.println("找不到主机: " + hostname);
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("I/O Error: " + e.getMessage());
            e.printStackTrace();
        }
        System.out.println("客户端已关闭。");
    }
}

如何运行

  1. 先运行服务器: java TCPServer

    • 控制台会显示: 服务器启动,正在监听端口 8888...,然后程序会停顿在 accept() 方法处,等待客户端。
  2. 再运行客户端: java TCPClient

    • 客户端控制台会显示: 已连接到服务器 localhost:8888
    • 你可以在客户端输入任何文本,"Hello Server!",然后按回车。
    • 服务器控制台会显示: 收到客户端消息: Hello Server!,并向客户端回显 服务器收到: Hello Server!
    • 客户端控制台会显示: 服务器响应: 服务器收到: Hello Server!
    • 在客户端输入 exit 并按回车,双方程序都会正常退出。

第二部分:UDP Socket 编程 (无连接)

UDP (User Datagram Protocol) 是一种无连接的、不可靠的协议,它就像寄明信片,你不需要和对方建立连接,直接把数据包(明信片)发出去,但不保证对方一定能收到,也不保证顺序。

核心概念

  1. DatagramSocket: 这是发送或接收数据报包的套接字。
  2. DatagramPacket: 表示一个数据报包,包含了要发送的数据、目标地址和端口,或者接收到的数据和源地址、端口。

步骤 1:创建 UDP 服务器

服务器只需要一个 DatagramSocket 在指定端口上等待接收数据包。

UDPServer.java

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPServer {
    public static void main(String[] args) {
        int port = 8888;
        byte[] buffer = new byte[1024]; // 缓冲区,用于接收数据
        try (DatagramSocket socket = new DatagramSocket(port)) {
            System.out.println("UDP 服务器启动,监听端口 " + port + "...");
            while (true) { // 持续等待接收数据
                // 创建一个 DatagramPacket 来接收数据
                DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);
                // receive() 方法会阻塞,直到收到一个数据包
                socket.receive(receivePacket);
                // 从数据包中提取数据
                String receivedMessage = new String(receivePacket.getData(), 0, receivePacket.getLength());
                System.out.println("收到来自 " + receivePacket.getAddress().getHostAddress() + " 的消息: " + receivedMessage);
                // 如果收到 "exit",则服务器也退出
                if ("exit".equalsIgnoreCase(receivedMessage)) {
                    System.out.println("服务器收到退出指令,准备关闭。");
                    break;
                }
                // 准备要发送的响应消息
                String responseMessage = "UDP服务器收到: " + receivedMessage;
                byte[] sendData = responseMessage.getBytes();
                // 创建一个新的 DatagramPacket 用于回复
                DatagramPacket sendPacket = new DatagramPacket(
                    sendData,
                    sendData.length,
                    receivePacket.getAddress(), // 回复到客户端的地址
                    receivePacket.getPort()     // 回复到客户端的端口
                );
                // 发送响应
                socket.send(sendPacket);
            }
        } catch (IOException e) {
            System.err.println("UDP 服务器异常: " + e.getMessage());
            e.printStackTrace();
        }
        System.out.println("UDP 服务器已关闭。");
    }
}

步骤 2:创建 UDP 客户端

客户端也需要一个 DatagramSocket,但它不需要 accept(),而是直接创建 DatagramPacket 发送,然后创建另一个 DatagramPacket 来接收。

UDPClient.java

import java.io.IOException;
import java.net.Datagram
分享:
扫描分享到社交APP
上一篇
下一篇