[网络] [TCP] Linux TCP Socket 学习指南

ChatGPT生成(2025年10月26日00:08:46)

🧠 Linux TCP Socket 学习指南

📘 一、什么是 TCP Socket?

1. TCP 与 Socket 的关系

  • TCP(Transmission Control Protocol):传输控制协议,提供可靠、面向连接的字节流通信。
  • Socket(套接字):是操作系统提供的一种编程接口,让程序员能使用 TCP/IP 协议进行通信。

简单来说:

Socket 就像是“网络中的文件句柄”,你可以用它来“读写”网络数据。

在 Linux 中,一切皆文件,Socket 也是一种特殊文件,你可以:

read() / write() / send() / recv() / close()

🧩 二、Socket 的创建与通信流程

我们以 TCP 为例,整个过程就像打电话:

阶段 客户端 服务端
创建套接字 socket() socket()
绑定地址 —— bind()
监听连接 —— listen()
连接请求 connect() accept()
数据传输 send()/recv() send()/recv()
断开连接 close() close()

🧱 三、服务端与客户端基本代码结构

✅ 服务端示例(server.c)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>

int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_len = sizeof(client_addr);
    char buffer[1024];

    // 1. 创建Socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        perror("socket error");
        exit(1);
    }

    // 2. 绑定地址和端口
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡
    server_addr.sin_port = htons(5000);       // 端口号

    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind error");
        exit(1);
    }

    // 3. 监听连接请求
    listen(server_fd, 5);
    printf("Server listening on port 5000...\n");

    // 4. 接受连接
    client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addr_len);
    printf("Client connected: %s\n", inet_ntoa(client_addr.sin_addr));

    // 5. 通信
    recv(client_fd, buffer, sizeof(buffer), 0);
    printf("Received: %s\n", buffer);
    send(client_fd, "Hello from server", 18, 0);

    // 6. 关闭
    close(client_fd);
    close(server_fd);
    return 0;
}

✅ 客户端示例(client.c)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>

int main() {
    int sock;
    struct sockaddr_in server_addr;
    char buffer[1024];

    // 1. 创建Socket
    sock = socket(AF_INET, SOCK_STREAM, 0);

    // 2. 服务器地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(5000);
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);

    // 3. 连接服务器
    connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));

    // 4. 发送/接收数据
    send(sock, "Hello Server", 12, 0);
    recv(sock, buffer, sizeof(buffer), 0);
    printf("From Server: %s\n", buffer);

    // 5. 关闭
    close(sock);
    return 0;
}

编译运行:

gcc server.c -o server
gcc client.c -o client
./server
# 另一个终端:
./client

⚙️ 四、Socket 常用函数讲解

函数名 作用 关键参数说明
socket() 创建套接字 AF_INET(IPv4), SOCK_STREAM(TCP)
bind() 绑定IP和端口 通常服务端用
listen() 开始监听 参数是最大等待队列长度
accept() 等待客户端连接 返回新的连接套接字
connect() 连接到服务器 客户端使用
send() / recv() 发送/接收数据 支持 flags 参数
close() 关闭连接 释放资源

📦 五、TCP Socket 常见选项与参数

1. setsockopt() / getsockopt()

用来设置或获取 Socket 选项。
原型:

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

2. 常见 TCP 参数

选项名 说明 示例
SO_REUSEADDR 允许端口重用 可避免 "Address already in use"
TCP_NODELAY 禁用 Nagle 算法(减少延迟) 对实时性要求高的应用使用
SO_RCVBUF / SO_SNDBUF 设置接收/发送缓冲区大小 优化性能
SO_KEEPALIVE TCP 保活检测 检测长连接是否断开

示例:

int opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

🧮 六、TCP 状态机与三次握手

🔁 三次握手过程

  1. 客户端 → SYN → 服务端
    请求建立连接。
  2. 服务端 → SYN + ACK → 客户端
    同意连接并回应。
  3. 客户端 → ACK → 服务端
    确认收到,连接建立完成。

此时双方可以开始通信。

🔚 四次挥手

断开连接时的过程:

  1. 客户端发送 FIN
  2. 服务端回 ACK
  3. 服务端再发 FIN
  4. 客户端回 ACK

🔍 七、常见 Socket 调试命令

命令 功能
netstat -anp 查看所有端口状态
ss -tulnp 查看TCP监听情况
lsof -i :5000 查看哪个进程占用端口
tcpdump -i eth0 port 5000 抓包分析 TCP 通信

📖 八、实践建议

  1. 从本地回环(127.0.0.1)开始实验。
  2. 尝试修改 SO_RCVBUF,观察传输速度。
  3. 使用 tcpdump 抓包,理解 TCP 三次握手。
  4. 了解非阻塞 I/O 和多路复用(select / poll / epoll)。

🎯 九、进阶方向(学习路线)

  1. 初级:

    • TCP/UDP Socket 基础编程
    • 多线程/多进程并发服务器
  2. 中级:

    • select / epoll 异步 I/O
    • TCP 参数调优、零拷贝
  3. 高级:

    • HTTP/HTTPS 协议实现
    • QUIC、TLS、安全传输层
    • 高性能服务器架构(如 Nginx、Redis)

💡 十、参考资料

  • 《Unix 网络编程(卷1)》—— W. Richard Stevens

  • man 手册:

    man 2 socket
    man 2 bind
    man 2 connect
    man 7 tcp
    
  • Linux 文档路径: /usr/include/linux/tcp.h

posted on 2025-10-26 00:09  风惊庭前叶  阅读(2)  评论(0)    收藏  举报