内核层理解socket和连接

个人主页:Lei宝啊 

愿所有美好如期而遇


本节我们将解释socket创建套接字的原理,我们现在能够理解到的是,调用socket系统调用,会创建好一个套接字并返回一个文件描述符。

现在,我们先来看这样一张图:

(我们以listen套接字为例)当我们调用系统调用创建一个套接字时,操作系统会在内核中为我们创建一个struct socket结构,我们现在可以将他理解成网络socket的入口,同时,struct file中有这样一个字段:void* private_data,他指向这个套接字,这个套接字中也有这样一个字段:struct file *file 回指向这个struct file,所以我们也就可以通过文件描述符找到struct file,再通过private_data找到socket。

我们看看socket的结构:

但是事实上,我们创建tcp连接时,内核创建的结构体叫做tcp_sock:

我们简单介绍几个字段:

但是这些我们不管,我们关心的是这个字段:

 struct inet_connection_sock,网络连接套接字:

icsk_timeout超时时间,icsk_retransmit_timer重传时间,我们关心的字段是struct request_sock_queue,他是什么呢?就是全连接队列:

当创建好tcp_sock时,他就会被挂在这个队列下,等待accept来获取。同时,我们仍然需要注意到这样一个字段:struct inet_sock:

我们可以看到daddr目的ip地址,saddr源ip地址,dport目的端口号,sport源端口号,这里面我们仍然可以看到一个字段:struct sock,同时,我们就发现,我们这里关注的字段都是处在最开始的位置。

struct sock里有这样两个字段:

我们常说tcp中有写缓冲区和读缓冲区,他们通过某种方式可以转换成上面的结构, sk_buff_head:

通过链表对sk_buff结构进行管理(每一个sk_buff管理着一个报文),sk_buff:

里面的tail和head管理着一段内存空间,这段内存空间就存放着协议栈的报文,通过这两个指针的移动对报文进行管理。

所以整体结构是这样的:

这样,我们通过sk指针就可以访问到这些结构体,如果我们想访问tcp_sock那么就强转成tcp_sock*,如果我们想访问inet_sock中的源端口目的端口就,就强转成inet_sock*。

对于udp来说,没有inet_connection_sock这个结构,socket辨别Udp和Tcp的方式就是我们刚开始说的socket中的type字段。

现在,我们来说普通套接字,当服务器完成三次握手后,OS就会创建好tcp_sock,然后将他连入到全连接队列中,当accept时,OS会首先创建struct file,接着是socket,然后通过socket中的sk指针和tcp_sock关联起来,将struct file的地址填入fd_arrry中,返回文件描述符,这样,普通套接字就创建好了,需要注意的是,普通套接字不关心全连接队列。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lei宝啊

觉得博主写的有用就鼓励一下吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值