深入解析Socket结构与实现
作者:Era_zhou | 来源:互联网 | 2024-11-24 12:00
本文详细介绍了Socket在Linux内核中的实现机制,包括基本的Socket结构、协议操作集以及不同协议下的具体实现。通过这些内容,读者可以更好地理解Socket的工作原理。
在Linux内核中,Socket是一种重要的网络通信工具,用户通过系统调用创建和管理Socket。每个Socket都由一个整数标识,称为套接字描述符。这个描述符在内核中被映射为一个复杂的结构体,该结构体包含了Socket的所有属性和数据。 ### 基本的Socket结构 `struct socket` 是最基本的BSD Socket结构体,无论用户创建何种类型的Socket,最初都会创建这个结构体。之后,根据不同的需求,会在其基础上进行扩展。`struct socket` 可以视为一个文件,因此可以在虚拟文件系统中安全地进行扩展。以下是 `struct socket` 的完整定义: ```c struct socket { socket_state state; unsigned long flags; const struct proto_ops *ops; struct fasync_struct *fasync_list; struct file *file; struct sock *sk; wait_queue_head_t wait; short type; }; ``` - **state**:表示Socket的状态,是一个枚举变量,主要用于TCP Socket,因为TCP是面向连接的协议。 - **flags**:一组标志位,目前在内核中并未实际使用。 - **ops**:一组协议相关的操作集,定义在 `struct proto_ops` 中。 - **type**:Socket的类型,例如 SOCK_STREAM 表示流式Socket,SOCK_DGRAM 表示数据报Socket。 ### 协议操作集 `struct proto_ops` 定义了一组协议相关的操作函数,用于处理不同类型的Socket。以下是 `struct proto_ops` 的定义: ```c struct proto_ops { int family; struct module *owner; int (*release)(struct socket *sock); int (*bind)(struct socket *sock, struct sockaddr *myaddr, int sockaddr_len); int (*connect)(struct socket *sock, struct sockaddr *vaddr, int sockaddr_len, int flags); int (*socketpair)(struct socket *sock1, struct socket *sock2); int (*accept)(struct socket *sock, struct socket *newsock, int flags); int (*getname)(struct socket *sock, struct sockaddr *addr, int *sockaddr_len, int peer); unsigned int (*poll)(struct file *file, struct socket *sock, struct poll_table_struct *wait); int (*ioctl)(struct socket *sock, unsigned int cmd, unsigned long arg); int (*listen)(struct socket *sock, int len); int (*shutdown)(struct socket *sock, int flags); int (*setsockopt)(struct socket *sock, int level, int optname, char __user *optval, int optlen); int (*getsockopt)(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen); int (*sendmsg)(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len); int (*recvmsg)(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len, int flags); int (*mmap)(struct file *file, struct socket *sock, struct vm_area_struct *vma); ssize_t (*sendpage)(struct socket *sock, struct page *page, int offset, size_t size, int flags); }; ``` 内核中定义了多个 `struct proto_ops` 实例,如 `myinet_stream_ops`、`myinet_dgram_ops` 和 `myinet_sockraw_ops`,分别对应流协议、数据报协议和原始套接字协议。 ### 网络层的Socket表示 在网络层,Socket由 `struct sock` 结构体表示。`struct sock` 比较复杂,包含了许多重要的成员变量,例如: - **sk_prot** 和 **sk_prot_creator**:指向特定协议的处理函数集,类型为 `struct proto`。 - **sk_state**:表示Socket的连接状态,比 `struct socket` 中的 `state` 更加精细。 - **sk_rcvbuf** 和 **sk_sndbuf**:分别表示接收和发送缓冲区的大小。 - **sk_receive_queue** 和 **sk_write_queue**:分别为接收缓冲队列和发送缓冲队列,队列中的每个元素是一个 `struct sk_buff`,表示一个套接字缓冲区。 ### INET域专用的Socket结构 `struct inet_sock` 是INET域专用的Socket结构体,在 `struct sock` 的基础上进行了扩展,提供了INET域特有的属性,如TTL、组播列表、IP地址和端口等。以下是 `struct inet_sock` 的定义: ```c struct inet_sock { struct sock sk; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct ipv6_pinfo *pinet6; #endif __u32 daddr; // IPv4的目的地址 __u32 rcv_saddr; // IPv4的本地接收地址 __u16 dport; // 目的端口 __u16 num; // 本地端口(主机字节序) __u32 saddr; // 发送地址 __s16 uc_ttl; // 单播的TTL __u16 cmsg_flags; struct ip_options *opt; __u16 sport; // 源端口 __u16 id; // 单调递增的一个值,用于赋给iphdr的id域 __u8 tos; // 服务类型 __u8 mc_ttl; // 组播的TTL __u8 pmtudisc; __u8 recverr:1, is_icsk:1, freebind:1, hdrincl:1, // 是否自己构建IP首部(用于raw协议) mc_loop:1; // 组播是否发向回路 int mc_index; // 组播使用的本地设备接口的索引 __u32 mc_addr; // 组播源地址 struct ip_mc_socklist *mc_list; // 组播组列表 struct { unsigned int flags; unsigned int fragsize; struct ip_options *opt; struct rtable *rt; int length; u32 addr; struct flowi fl; } cork; }; ``` ### 其他协议专用的Socket结构 - **RAW协议**:`struct raw_sock` 是RAW协议专用的Socket结构体,在 `struct inet_sock` 的基础上进行了扩展,主要处理ICMP协议的过滤设置。 - **UDP协议**:`struct udp_sock` 是UDP协议专用的Socket结构体,在 `struct inet_sock` 的基础上进行了扩展,主要处理UDP协议的特定功能。 - **TCP协议**:`struct tcp_sock` 是TCP协议专用的Socket结构体,在 `struct inet_connection_sock` 的基础上进行了扩展,增加了滑动窗口协议和拥塞控制算法等TCP特有的属性。 - **TIME-WAIT状态**:`struct tcp_timewait_sock` 是在 `struct inet_timewait_sock` 的基础上进行扩展,用于处理TCP连接的TIME-WAIT状态。 - **请求Socket**:`struct tcp_request_sock` 是在 `struct inet_request_sock` 的基础上进行扩展,用于处理TCP连接的初始请求阶段。 通过以上内容,我们可以更全面地理解Socket在Linux内核中的实现机制,从而更好地进行网络编程和故障排查。
推荐阅读
本文详细介绍了如何在PHP中使用Memcached进行数据缓存,包括服务器连接、数据操作、高级功能等。 ...
[详细]
蜡笔小新 2024-11-24 09:51:34
一、使用Microsoft.Office.Interop.Excel.DLL需要安装Office代码如下:2publicstaticboolExportExcel(S ...
[详细]
蜡笔小新 2024-11-23 16:37:33
探讨了经典算法题目——汽车加油行驶问题,通过网络流和费用流的视角,深入解析了该问题的解决方案。本文将详细阐述如何利用最短路径算法解决这一问题,并提供详细的代码实现。 ...
[详细]
蜡笔小新 2024-11-21 14:21:38
我在尝试将组合框转换为具有自动完成功能时遇到了一个问题,即页面上的列表框也被转换成了自动完成下拉框,而不是保持原有的多选列表框形式。 ...
[详细]
蜡笔小新 2024-11-24 12:02:48
涵盖最新的网络安全动态,包括OpenSSH和WordPress的安全更新、VirtualBox提权漏洞、以及谷歌推出的新证书验证机制等内容。 ...
[详细]
蜡笔小新 2024-11-24 10:29:06
做过web测试的小伙伴们都知道,web元素现在很多是JS写的,那么既然是JS写的,可以通过JS语言去操作页面,来帮助我们操作一些selenium不能覆盖的功能。问题来了我们能否通过 ...
[详细]
蜡笔小新 2024-11-24 03:05:20
本文介绍了如何通过安装和配置php_uploadprogress扩展来实现文件上传时的进度条显示功能。通过一个简单的示例,详细解释了从安装扩展到编写具体代码的全过程。 ...
[详细]
蜡笔小新 2024-11-24 00:04:13
本文详细探讨了TCP协议下的粘包现象及其产生的原因,并提供了通过自定义报头解决粘包问题的具体实现方案。同时,对比了TCP与UDP协议在数据传输上的不同特性。 ...
[详细]
蜡笔小新 2024-11-23 15:55:15
汇总了2023年7月7日最新的网络安全新闻和技术更新,包括最新的漏洞披露、工具发布及安全事件。 ...
[详细]
蜡笔小新 2024-11-23 13:35:48
本文详细介绍如何在SSM(Spring + Spring MVC + MyBatis)框架中实现分页功能。包括分页的基本概念、数据准备、前端分页栏的设计与实现、后端分页逻辑的编写以及最终的测试步骤。 ...
[详细]
蜡笔小新 2024-11-23 11:40:33
本文详细介绍了 Node.js 中 OS 模块的 arch 方法,包括其功能、语法、参数以及返回值,并提供了具体的使用示例。 ...
[详细]
蜡笔小新 2024-11-23 10:19:37
Asynchronous JavaScript and XML (AJAX) 的流行很大程度上得益于 Google 在其产品如 Google Suggest 和 Google Maps 中的应用。本文将深入探讨 AJAX 在 .NET 环境下的工作原理及其实现方法。 ...
[详细]
蜡笔小新 2024-11-22 18:18:57
hlg_oj_1116_选美大赛这题是最长子序列,然后再求出路径就可以了。开始写的比较乱,用数组什么的,后来用了指针就好办了。现在把代码贴 ...
[详细]
蜡笔小新 2024-11-22 09:20:30
长期从事ABAP开发工作的专业人士,在面对行业新趋势时,往往需要重新审视自己的发展方向。本文探讨了几位资深专家对ABAP未来走向的看法,以及开发者应如何调整技能以适应新的技术环境。 ...
[详细]
蜡笔小新 2024-11-21 18:21:06
目录一、综述二、INET的初始化2.1INET接口注册2.2抽象实体的建立2.3代码细节分析2.3.1socket参数三、其他协议3.1PF_PACKET3.2P ...
[详细]
蜡笔小新 2024-11-20 15:21:14