【Linux】Linux内核的网络协议之socket理解

1. Socket(套接字) 的本质

  • 它是应用程序与网络协议栈之间的编程接口(API),用于实现网络通信。
    Socket 并不是一个物理设备,而是一个抽象层
  • 为应用程序提供统一的网络操作接口(如 send()recv()bind()connect() 等)。
  • 屏蔽底层协议(TCP、UDP、IP 等)的复杂性,让开发者更专注于业务逻辑。
  • 在 Linux 内核中,Socket 是一个文件描述符(File Descriptor, fd),遵循“一切皆文件”的设计哲学。

2. Socket 在网络协议栈中的位置

Linux 网络协议栈的分层如下:

+-----------------------+
|   Application Layer   |  (e.g., HTTP, FTP, SSH)
+-----------------------+
|        Socket         |  ← 应用程序与内核的接口
+-----------------------+
|   Transport Layer     |  (TCP/UDP)
+-----------------------+
|    Network Layer      |  (IP, ICMP)
+-----------------------+
|   Link Layer (MAC)    |  (Ethernet, ARP)
+-----------------------+
|   Physical Layer      |  (网卡驱动、硬件)
+-----------------------+

Socket 的作用就是连接“应用程序”和“传输层”(TCP/UDP)。


3. Socket 的类型

Linux 支持多种 Socket,常见的有:

Socket 类型协议特点
SOCK_STREAMTCP可靠、面向连接、字节流传输
SOCK_DGRAMUDP不可靠、无连接、数据报传输
SOCK_RAW原始 IP直接访问 IP 层(如 ping)

4. Socket 的工作流程(以 TCP 为例)

服务器端(Server)

  1. socket() – 创建一个 Socket(返回 fd)。
  2. bind() – 绑定 IP 和端口。
  3. listen() – 监听客户端连接。
  4. accept() – 接受客户端连接(返回新 fd)。
  5. read()/write() – 与客户端通信。
  6. close() – 关闭连接。

客户端(Client)

  1. socket() – 创建 Socket。
  2. connect() – 连接服务器。
  3. write()/read() – 发送/接收数据。
  4. close() – 关闭连接。

5. Socket 在内核中的实现

Linux 内核用 struct socket 表示一个 Socket,关键数据结构:

// 表示一个 Socket(内核层面)
struct socket {
    struct sock     *sk;       // 指向 sock(存储协议状态)
    const struct proto_ops *ops; // 协议操作(TCP/UDP)
    // ...
};

// 存储协议状态(TCP/UDP 连接信息)
struct sock {
    struct inet_sock    inet;   // IP 和端口信息
    struct sk_buff_head receive_queue; // 接收队列(存放数据包)
    // ...
};
  • sk_buff(Socket Buffer):内核用这个结构管理网络数据包。
  • proto_ops:定义协议操作(如 TCP 的 connectsendmsg 等)。

6. Socket 与文件描述符(fd)的关系

  • 当调用 socket() 时,内核会:
    1. 创建一个 struct socket 结构。
    2. 分配一个文件描述符(fd),并关联到该 Socket。
  • 之后,应用程序可以用 read(fd, ...)write(fd, ...) 等文件操作函数进行网络通信。

示例:

int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建 TCP Socket
write(sockfd, "Hello", 5); // 发送数据(类似写文件)
close(sockfd); // 关闭 Socket(类似关闭文件)

7. 如何查看 Linux 中的 Socket?

(1)ss 命令(推荐)

ss -tulnp  # 查看所有 TCP/UDP Socket
  • -t:TCP
  • -u:UDP
  • -l:监听中的 Socket
  • -n:不解析服务名(直接显示端口号)
  • -p:显示进程信息

(2)netstat 命令(较旧)

netstat -tulnp

(3)/proc/net/tcp/proc/net/udp

cat /proc/net/tcp  # 查看内核中的 TCP Socket 状态
cat /proc/net/udp  # 查看 UDP Socket

8. 常见问题

Q1: Socket 和文件描述符(fd)有什么区别?

  • Socket 是网络通信的抽象,属于内核对象。
  • 文件描述符(fd) 是用户空间访问 Socket 的句柄(整数)。

Q2: 一个进程可以有多少个 Socket?

取决于 ulimit -n(文件描述符限制),默认通常是 1024,但可以调整。

Q3: Socket 和 TCP/UDP 是什么关系?

  • Socket 是接口,TCP/UDP 是协议。
  • SOCK_STREAM → TCP
  • SOCK_DGRAM → UDP

总结

概念说明
Socket应用程序与网络协议栈之间的接口,用文件描述符(fd)表示。
TCP Socket可靠、面向连接(SOCK_STREAM)。
UDP Socket不可靠、无连接(SOCK_DGRAM)。
内核实现通过 struct socketstruct sock 管理连接状态和数据包。

Socket 是 Linux 网络编程的核心,理解它有助于分析网络问题(如 TIME_WAITCLOSE_WAIT 状态)或开发高性能服务器(如 Nginx、Redis)。


https://github.com/0voice

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值