【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_STREAM | TCP | 可靠、面向连接、字节流传输 |
SOCK_DGRAM | UDP | 不可靠、无连接、数据报传输 |
SOCK_RAW | 原始 IP | 直接访问 IP 层(如 ping) |
4. Socket 的工作流程(以 TCP 为例)
服务器端(Server)
socket()
– 创建一个 Socket(返回 fd)。bind()
– 绑定 IP 和端口。listen()
– 监听客户端连接。accept()
– 接受客户端连接(返回新 fd)。read()/write()
– 与客户端通信。close()
– 关闭连接。
客户端(Client)
socket()
– 创建 Socket。connect()
– 连接服务器。write()/read()
– 发送/接收数据。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 的connect
、sendmsg
等)。
6. Socket 与文件描述符(fd)的关系
- 当调用
socket()
时,内核会:- 创建一个
struct socket
结构。 - 分配一个文件描述符(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
→ TCPSOCK_DGRAM
→ UDP
总结
概念 | 说明 |
---|---|
Socket | 应用程序与网络协议栈之间的接口,用文件描述符(fd)表示。 |
TCP Socket | 可靠、面向连接(SOCK_STREAM )。 |
UDP Socket | 不可靠、无连接(SOCK_DGRAM )。 |
内核实现 | 通过 struct socket 和 struct sock 管理连接状态和数据包。 |
Socket 是 Linux 网络编程的核心,理解它有助于分析网络问题(如 TIME_WAIT
、CLOSE_WAIT
状态)或开发高性能服务器(如 Nginx、Redis)。
https://github.com/0voice