Linux 网络相关系统调用按功能可分为套接字创建与管理、连接建立与终止、数据收发、套接字选项与信息、I/O 多路复用、网络接口控制六大类是用户态网络编程的核心接口。套接字创建与基础管理socket()创建通信端点套接字返回文件描述符。int socket(int domain, int type, int protocol);domain地址族AF_INET/AF_INET6type套接字类型SOCK_STREAM/SOCK_DGRAMprotocol协议0 默认socketpair()创建一对已连接的无名套接字多用于进程间通信。close()关闭套接字释放内核资源。shutdown()单向关闭读写通道SHUT_RD/SHUT_WR/SHUT_RDWR。连接建立与终止TCP 为主bind()绑定套接字到本地地址 端口服务器必用。int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);listen()将套接字设为被动监听模式设置连接队列长度。int listen(int sockfd, int backlog);accept()从监听队列接受连接返回新通信套接字。int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);connect()客户端发起连接请求TCP 三次握手。int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);数据收发TCP/UDP 通用1. 面向连接TCPsend()/recv()基础收发支持 flags 控制MSG_OOB/MSG_PEEK。ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t recv(int sockfd, void *buf, size_t len, int flags);sendmsg()/recvmsg()支持分散 / 聚集 IO、控制信息如辅助数据功能更强大。2. 无连接UDPsendto()/recvfrom()收发时指定 / 获取对方地址无需提前连接。ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);套接字选项与信息查询setsockopt()/getsockopt()设置 / 获取套接字选项超时、缓冲区大小、端口复用等。int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);getsockname()获取套接字本地地址。getpeername()获取连接对方地址。I/O 多路复用高并发核心select()跨平台多路复用监听 fd 集合的读写异常事件。poll()改进 select无 fd 数量限制效率更高。epoll 系列Linux 特有epoll_create()创建 epoll 实例。epoll_ctl()注册 / 修改 / 删除监听 fd。epoll_wait()等待事件触发返回就绪 fd 列表。网络接口与底层控制ioctl()通用设备控制常用于网卡配置IP、子网掩码、MAC、路由操作。int ioctl(int fd, unsigned long request, ...);fcntl()文件控制可设置套接字非阻塞、获取 / 设置文件状态标志。典型流程对比TCP 服务器socket() → bind() → listen() → accept() → send()/recv() → close()TCP 客户端socket() → connect() → send()/recv() → close()UDP 服务器 / 客户端socket() → bind()可选客户端→ recvfrom()/sendto() → close()LSM 网络基础架构LSMLinux Security Module是内核安全框架通过CONFIG_SECURITY启用提供200 钩子其中 ** 网络钩子socket/sk_buff** 管控全链路网络行为。核心网络钩子Socket 层拦截所有 socket 系统调用对应网络编程核心接口socket_create创建套接字控制类型 / 协议族socket_bind绑定地址 端口防止特权端口滥用socket_connect发起连接控制目标 IP / 端口socket_listen监听端口socket_accept接受连接socket_sendmsg/socket_recvmsg数据收发过滤内容 / 方向socket_getsockname/getpeername获取地址信息socket_setsockopt/getsockopt套接字选项控制核心网络钩子数据包层sk_buff配合 Netfilter对数据包进行标签化管控netif_receive_skb网卡收包ip_local_outIP 层发包skb_security_set/get读写数据包安全标签SELinux/Smack 用secmark基于 Netfilter 规则打标签iptables 配合BPF‑LSM5.7eBPF 动态策略网络模型eBPF 程序挂载 LSM 钩子动态自定义策略核心特性无需内核模块 / 重启bpftool动态加载支持所有网络钩子socket、sk_buff、Netfilter示例阻断进程连接192.168.1.100:22、限制bind端口范围优势可编程、动态更新、与 eBPF 生态融合局限需 5.7 内核、eBPF 编程门槛典型场景云原生、微服务、零信任安全典型调用流程以connect()为例用户态connect(fd, addr, len)系统调用内核态sys_connect()→security_socket_connect()LSM 框架遍历所有已启用模块的socket_connect钩子SELinux检查进程域如user_t是否允许连接目标端口类型如ssh_port_tAppArmor检查进程 Profile 是否允许network inet tcp到目标 IPBPF‑LSM执行挂载的 eBPF 程序动态判断放行 / 拒绝结果钩子返回 0 允许-EPERM拒绝系统调用失败绕过系统调用普通标准 Socket绝对跳不过系统调用常规socket/connect/send/recv网络程序TCP/UDP 必须走内核网络协议栈只要用内核协议栈收发、建连、绑定端口全都要陷入内核必须触发syscall 陷入x86int 0x80/syscall指令ARMsvc原因端口管理、路由、IP 分片、TCP 重传 / 拥塞控制全在内核网卡硬件中断、DMA 收发只有内核能访问资源隔离用户态无权直接操作网卡、内核路由表 标准 POSIX Socket无法跳过系统调用。绕开 Socket 系统调用用户态收发包跳过内核协议栈可以完全不用 socket 系列系统调用直接用户态读写网卡自己实现二层 / 三层协议。1. 实现方案常用 3 种① RAW 裸套接字还没完全跳系统调用但绕开协议栈socket(AF_INET, SOCK_RAW, IPPROTO_TCP);仍要创建 socket 系统调用但自己构造 IP/TCP 报文内核不做协议解析、不做重组、不做重传能自由发包、伪造源 IP / 端口② PACKET 套接字链路层最常用socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));直接拿到以太网帧到 MAC 层完全绕开内核 TCP/UDP/IP 协议栈自己在用户态实现ARP、IP、TCP、UDP③ DPDK / AF_XDP真正大规模跳过系统调用企业级高性能用户态网络标配内核旁路、无系统调用、无中断、无拷贝直接用户态映射网卡 DMA 缓冲区轮询收发包全程无 syscall 陷入自己在用户态完整实现协议栈librte_ip、用户态 TCP 栈关键技术UIO / VFIO 把网卡设备直接透传给用户态内存大页、零拷贝、轮询模式替代中断彻底不调用 socket/send/recv 任何系统调用最硬核彻底无任何系统调用 网络通信原理通过mmap 映射网卡物理寄存器 / DMA 环形队列到用户态用户态直接写网卡寄存器、填充 DMA 描述符网卡 DMA 直接和用户态内存交互全程一条系统调用都不执行限制需要网卡硬件支持、驱动支持用户态映射需要 root 权限、设备权限必须自己实现二层 三层 四层协议不能和内核协议栈共存端口冲突、路由冲突典型场景DPDK 网关、防火墙、负载均衡金融低时延交易网络微秒级杜绝 syscall 陷入开销自研私有协议栈RAW / PACKET 涉及系统调用清单RAW / AF_PACKET 不可能跳过系统调用创建、收发、绑网卡、设选项 全依赖内核 syscall。只是绕开了内核 TCP/UDP 协议栈但没绕开系统调用。必用socketsendtorecvfromclose高频常用bindsetsockoptgetsockoptioctlfcntl进阶 / 高性能sendmsgrecvmsgmmapmunmapbpfRAW 套接字 / PACKET 套接字 都不需要 connect ()TCP 是面向连接的协议connect()触发三次握手建立一条固定的源 IP: 端口 → 目标 IP: 端口链路之后send/recv不需要再传地址但RAW/PACKET 是无连接模式内核不维护连接状态。RAW 调用connect()不会建立任何连接不会握手不会发包。它只做一件事把这个 RAW socket绑定到一个固定目标 IP之后可以直接用send()发不用每次填地址。connect(raw_fd, (struct sockaddr*)dest_addr, sizeof(dest_addr)); send(raw_fd, pkt, pkt_len, 0); // 不用目标地址了总结RAW 的 connect 只是简化 API无任何网络连接行为。PACKET 工作在以太网帧级别没有 “连接” 概念。Linux 虽然允许你对AF_PACKET调用connect()但没有任何实际网络行为不能减少系统调用不能加速发包绝大多数工具tcpdump、抓包、注入从不使用为什么普通程序不这么做协议栈工作量巨大要自己实现ARP、IP 分片、TCP 三次握手、滑动窗口、重传、拥塞控制、定时器。不兼容标准 Socket 生态需要 root、依赖硬件、开发复杂度极高内核协议栈已经高度优化普通业务没必要造轮子关键要点标准 TCP/UDP Socket 程序必须走系统调用无法跳过RAW/PACKET 裸包绕开内核协议栈但仍需少量 socket 系统调用DPDK/AF_XDP/VFIO 用户态网卡完全跳过系统调用、内核协议栈用户态直接收发网络包能实现但只适合高性能网关、低时延交易、安全抓包攻防场景不适合业务开发总结基础通信socket/bind/listen/accept/connect/send/recv高效 IOepollLinux/select/poll选项控制setsockopt/getsockopt/ioctl