Socket 详解:零基础入门教程

Socket 详解:零基础入门教程

1. 什么是 Socket?

Socket(套接字)是网络通信的抽象接口,用于在不同设备之间传输数据。类比于两个城市之间的电话线,一端拨号(客户端),另一端接听(服务器),双方通过线路交换数据。Socket 的主要作用是实现客户端和服务器之间的双向通信,支持 TCP 和 UDP 协议。

2. Socket 的类型
2.1 基于 TCP 的 Socket

基于 TCP 的 Socket 是面向连接的,提供可靠的数据传输,确保数据不丢失且有序传输。适用于文件传输、网页浏览(HTTP)、邮件(SMTP)等场景。核心类包括 ServerSocket(服务器端监听连接)和 Socket(客户端和服务器的通信端点)。

2.2 基于 UDP 的 Socket

基于 UDP 的 Socket 是无连接的,传输速度快,但可能丢包。适用于视频流、实时游戏、广播消息等场景。核心类包括 DatagramSocket(发送和接收数据包)和 DatagramPacket(封装数据包)。

3. TCP Socket 编程步骤
3.1 服务器端(Server)

服务器端通过 ServerSocket 监听指定端口,等待客户端连接。连接建立后,通过 Socket 获取输入输出流,与客户端进行数据交互,最后关闭资源。

// 示例:TCP 服务器端
import java.io.*;
import java.net.*;

public class TCPServer {
    public static void main(String[] args) throws IOException {
        // 1. 创建 ServerSocket,监听 8888 端口
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务器已启动,等待连接...");
        
        // 2. 等待客户端连接(阻塞直到有连接)
        Socket clientSocket = serverSocket.accept();
        System.out.println("客户端已连接:" + clientSocket.getInetAddress());
        
        // 3. 获取输入输出流
        BufferedReader in = new BufferedReader(
            new InputStreamReader(clientSocket.getInputStream())
        );
        PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
        
        // 4. 处理数据:读取客户端消息并回复
        String clientMessage = in.readLine();
        System.out.println("客户端说:" + clientMessage);
        out.println("你好,我是服务器!");
        
        // 5. 关闭资源
        in.close();
        out.close();
        clientSocket.close();
        serverSocket.close();
    }
}

3.2 客户端(Client)

客户端通过 Socket 连接服务器的指定 IP 和端口,获取输入输出流,向服务器发送请求并接收响应,最后关闭资源。

// 示例:TCP 客户端
import java.io.*;
import java.net.*;

public class TCPClient {
    public static void main(String[] args) throws IOException {
        // 1. 创建 Socket,连接服务器的 8888 端口
        Socket socket = new Socket("localhost", 8888);
        System.out.println("已连接到服务器...");
        
        // 2. 获取输入输出流
        BufferedReader in = new BufferedReader(
            new InputStreamReader(socket.getInputStream())
        );
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        
        // 3. 发送消息
        out.println("你好,我是客户端!");
        
        // 4. 接收服务器响应
        String serverResponse = in.readLine();
        System.out.println("服务器回复:" + serverResponse);
        
        // 5. 关闭资源
        in.close();
        out.close();
        socket.close();
    }
}

4. UDP Socket 编程步骤
4.1 发送方(Sender)

发送方通过 DatagramSocket 发送数据包,无需绑定端口。数据包通过 DatagramPacket 封装,指定目标 IP 和端口,最后关闭资源。

// 示例:UDP 发送方
import java.net.*;

public class UDPSender {
    public static void main(String[] args) throws IOException {
        // 1. 创建 DatagramSocket
        DatagramSocket socket = new DatagramSocket();
        
        // 2. 封装数据包(目标地址为 localhost:9999)
        String message = "Hello UDP!";
        byte[] data = message.getBytes();
        InetAddress address = InetAddress.getByName("localhost");
        DatagramPacket packet = new DatagramPacket(data, data.length, address, 9999);
        
        // 3. 发送数据
        socket.send(packet);
        System.out.println("消息已发送!");
        
        // 4. 关闭资源
        socket.close();
    }
}

4.2 接收方(Receiver)

接收方通过 DatagramSocket 绑定指定端口,准备数据包接收数据。通过 receive() 方法阻塞等待数据包,解析发送方的信息,最后关闭资源。

// 示例:UDP 接收方
import java.net.*;

public class UDPReceiver {
    public static void main(String[] args) throws IOException {
        // 1. 创建 DatagramSocket,绑定 9999 端口
        DatagramSocket socket = new DatagramSocket(9999);
        
        // 2. 准备数据包
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        
        // 3. 接收数据(阻塞直到有数据)
        socket.receive(packet);
        String message = new String(packet.getData(), 0, packet.getLength());
        System.out.println("收到消息:" + message);
        
        // 4. 关闭资源
        socket.close();
    }
}

代码详细注释
  • TCPServer.java:服务器端代码,监听指定端口,等待客户端连接,处理客户端消息并回复。
  • TCPClient.java:客户端代码,连接服务器,发送消息并接收服务器响应。
  • UDPSender.java:UDP 发送方代码,发送数据包到指定目标地址。
  • UDPReceiver.java:UDP 接收方代码,绑定指定端口,接收并处理数据包。

 

5. 核心知识点总结
概念说明
IP 地址与端口IP 标识设备,端口标识应用程序(范围:0-65535,0-1023 为系统保留)
TCP vs UDPTCP 可靠但慢,UDP 快但不可靠。
阻塞与非阻塞accept()receive() 是阻塞方法,直到有连接或数据到达。
多客户端处理服务器端可通过多线程或线程池处理多个客户端请求(示例见下文补充)。
数据格式通常使用字符串、JSON 或二进制数据(如图片、文件)。

6. 常见问题与解决方案
  1. 连接超时:检查目标 IP 和端口是否正确,防火墙是否开放。
  2. 数据乱码:确保发送和接收的字符编码一致(如 UTF-8)。
  3. 资源未关闭:使用 try-with-resources 自动关闭资源(Java 7+)。
    try (Socket socket = new Socket("localhost", 8888)) {
        // 使用 socket
    } catch (IOException e) {
        e.printStackTrace();
    }
    

  4. 端口占用:通过 netstat -ano 查看端口占用情况,终止占用进程。

7. 扩展:多线程处理多客户端
// 多线程服务器示例
public class MultiThreadServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);
        while (true) {
            Socket clientSocket = serverSocket.accept();
            // 为每个客户端创建新线程
            new Thread(() -> {
                try (BufferedReader in = new BufferedReader(
                        new InputStreamReader(clientSocket.getInputStream()));
                     PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {
                    String request = in.readLine();
                    out.println("处理后的响应:" + request);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}


8. 测试你的 Socket 程序
  1. 本地测试:服务器和客户端都运行在同一台机器,IP 使用 localhost
  2. 跨网络测试:确保设备在同一局域网,使用内网 IP(如 192.168.x.x)。
  3. 使用 Telnet:快速测试 TCP 服务器(命令:telnet IP 端口)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值