TCP源码浅读(4)三次握手-被动方接收SYN

版本:linux 4.18.1

作为学习笔记,本篇只讨论常规的交互过程,旨在理清 linux 内核对 TCP 相关的信息管理。

服务端调用 listen 函数后一直处于 TCP_LISTEN 状态,等待客户端的连接请求;

上一节我们分析了第一握手,客户端发送了 SYN 包,现在我们来看下服务端接收 SYN 包后的处理过程。

 内核收到任何 TCP 消息,都会进入该函数。首先在全局的 tcp_hashinfo 中查找 sock,然后进行相应的处理。

看下查找函数 __inet_lookup

查找过程是先查 ehash,然后再查 inet_listen_hashbucket

服务端在接收到 SYN 包的时候,还没有可以表示这个连接的 sock 存在 ehash 中,所以要继续 inet_listen_hashbucket 中查找。

inet_listen_hashbucket 保存的了服务端调用 listen 函数时插入的 sock,它处于 TCP_LISTEN 状态,端口号等于 SYN 请求包的目的端口,因此,这里可以找到这个 sock。

找到以上 sock 后,服务端要创建一个 request_sock 对象来表示这个 半连接,最后要构建 SYN+ACK 响应包发送给客户端,即向客户端发送 第二次握手

inet_reqsk_alloc() 函数创建一个 request_sock 对象来表示这个半连接,然后将它添加到 ehash 中,在网上经常会看到说服务器在收到 SYN 请求包后,会创建一个 socket 保存到半连接队列,但实际上 ehash 是个 hash 表,只是它又使用了链表来解决 hash 冲突;

此外,服务端还要更新一下半连接数;我们知道,半连接数是针对服务端监听 socket 而言的,而该 sock 正是第一步在  inet_listen_hashbucket 中查找到的那个 socket更新值:sk.icsk_accept_queue.qlen++

这里还有个地方需要注意, 代表这个半连接的 request_sock 的状态是 TCP_NEW_SYN_RECV,不是 TCP_SYN_RECV,这和以前学到的三次握手状态转换图有点出入。

查阅资料发现这个状态是 Linux 4.4+ 以后新增的本文主要以理清握手过程为主,暂不深究为什么新增这个状态,以后再探讨。

服务端发送第二次握手后,内核中保存的 tcp 相关信息如下所示:

未完待续... 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值