热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入解析Socket结构与实现

本文详细介绍了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进行数据缓存,包括服务器连接、数据操作、高级功能等。 ... [详细]
  • 一、使用Microsoft.Office.Interop.Excel.DLL需要安装Office代码如下:2publicstaticboolExportExcel(S ... [详细]
  • 洛谷 P4009 汽车加油行驶问题 解析
    探讨了经典算法题目——汽车加油行驶问题,通过网络流和费用流的视角,深入解析了该问题的解决方案。本文将详细阐述如何利用最短路径算法解决这一问题,并提供详细的代码实现。 ... [详细]
  • 我在尝试将组合框转换为具有自动完成功能时遇到了一个问题,即页面上的列表框也被转换成了自动完成下拉框,而不是保持原有的多选列表框形式。 ... [详细]
  • 2023年1月28日网络安全热点
    涵盖最新的网络安全动态,包括OpenSSH和WordPress的安全更新、VirtualBox提权漏洞、以及谷歌推出的新证书验证机制等内容。 ... [详细]
  • selenium通过JS语法操作页面元素
    做过web测试的小伙伴们都知道,web元素现在很多是JS写的,那么既然是JS写的,可以通过JS语言去操作页面,来帮助我们操作一些selenium不能覆盖的功能。问题来了我们能否通过 ... [详细]
  • 本文介绍了如何通过安装和配置php_uploadprogress扩展来实现文件上传时的进度条显示功能。通过一个简单的示例,详细解释了从安装扩展到编写具体代码的全过程。 ... [详细]
  • Python网络编程:深入探讨TCP粘包问题及解决方案
    本文详细探讨了TCP协议下的粘包现象及其产生的原因,并提供了通过自定义报头解决粘包问题的具体实现方案。同时,对比了TCP与UDP协议在数据传输上的不同特性。 ... [详细]
  • 汇总了2023年7月7日最新的网络安全新闻和技术更新,包括最新的漏洞披露、工具发布及安全事件。 ... [详细]
  • 本文详细介绍如何在SSM(Spring + Spring MVC + MyBatis)框架中实现分页功能。包括分页的基本概念、数据准备、前端分页栏的设计与实现、后端分页逻辑的编写以及最终的测试步骤。 ... [详细]
  • 本文详细介绍了 Node.js 中 OS 模块的 arch 方法,包括其功能、语法、参数以及返回值,并提供了具体的使用示例。 ... [详细]
  • Asynchronous JavaScript and XML (AJAX) 的流行很大程度上得益于 Google 在其产品如 Google Suggest 和 Google Maps 中的应用。本文将深入探讨 AJAX 在 .NET 环境下的工作原理及其实现方法。 ... [详细]
  • hlg_oj_1116_选美大赛这题是最长子序列,然后再求出路径就可以了。开始写的比较乱,用数组什么的,后来用了指针就好办了。现在把代码贴 ... [详细]
  • 长期从事ABAP开发工作的专业人士,在面对行业新趋势时,往往需要重新审视自己的发展方向。本文探讨了几位资深专家对ABAP未来走向的看法,以及开发者应如何调整技能以适应新的技术环境。 ... [详细]
  • linux网络子系统分析(二)—— 协议栈分层框架的建立
    目录一、综述二、INET的初始化2.1INET接口注册2.2抽象实体的建立2.3代码细节分析2.3.1socket参数三、其他协议3.1PF_PACKET3.2P ... [详细]
author-avatar
Era_zhou
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有