1. 应用层

1.1 server

socket() -> bind() -> listen() -> accept() -> recv() & send()

1.2 client

socket() ->  connect() -> send() & recv()

1.3 三次握手建立连接

(1) 客户端发送一个 SYN 段(SYN 标志位置位),包含初始序号 ISN,在图中,这个序号的值 seq = 2379453243. 在这个过程中,客户端是通过 connect 函数发起连接请求的,此时 connect 函数阻塞,等待服务器发回 ACK 应答。

(2) 服务器端接收到 SYN 段后(通过listen监听),知道有新的连接请求到来,于是初始化一个序号 ISN,在上面的例子中这个值是 seq = 4269857. 此时服务器创建一个 TCP 段,将 SYN 和 ACK 标志置位,让 seq = 4269857, ack = 2379453244,然后将这个 TCP 段发送给客户端。这个步骤完全有内核完成,并将此连接加入未完成连接队列。

(3) 客户端再次收到服务器发送来的 TCP 段后,检查到带有 SYN 和 ACK 标志,于是客户端一方连接已经建立成功,此时 connect 函数返回。客户端创建一个 TCP 段,将 ACK 标志置位,同时将 ack 的值设置为 4269858,发送给服务器。

(4) 服务器收到客户端的 ACK 后,将此连接移到已完成连接队列(accept)。

2. kernel流程

2.1 client 通过connect()发送SYN报文,向服务器发起tcp连接

connect ----> SYSCALL_DEFINE3(__sys_connect)(socket.c) -> sock->ops->connect -> inet_stream_connect(af_inet.c) -> __inet_stream_connect -> sk->sk_prot->connect -> tcp_v4_connect(tcp_ipv4.c) -> tcp_connect(tcp_output.c) -> tcp_send_syn_data | tcp_transmit_skb(syn)

tcp_connect(): Build a SYN and send it off

对于阻塞调用,等待后续握手的完成;对于非阻塞调用,则直接返回 -EINPROGRESS,然后在select函数中来捕获socket的连接、读写、异常事件以触发相关操作。

2.2 tcp_rcv_state_process(三次握手状态机)

网卡驱动 --> netif_receive_skb - --> ip_rcv ---> ip_local_deliver_finish ---> tcp_v4_rcv -> tcp_v4_do_rcv -> tcp_rcv_state_process

1) client

客户端收到SYN+ACK报文,然后回ACK报文

case TCP_SYN_SENT: tcp_rcv_synsent_state_process -> tcp_finish_connect & tcp_send_ack

client tcp state: CLOSING ->  TCP_SYN_SENT -> TCP_ESTABLISHED

2) server

a. 收到客户端SYN报文, 发送SYN+ACK报文

case TCP_LISTEN: icsk->icsk_af_ops->conn_request -> tcp_v4_conn_request -> tcp_conn_request -> af_ops->send_synack -> tcp_v4_send_synack

tcp_v4_send_synack(): Send a SYN-ACK after having received a SYN.

server tcp state变为TCP_NEW_SYN_RECV

b. 收到客户端ACK报文

连接已经建立,唤醒阻塞的accept函数。

首先在tcp_v4_rcv中,建一个新的sock进入TCP_SYN_RECV状态;

然后调用tcp_child_process -> tcp_rcv_state_process,最终进入TCP_ESTABLISHED状态,并放入accept队列通知select/epoll。

server tcp state:  CLOSING ->  TCP_LISTEN ->  TCP_NEW_SYN_RECV -> TCP_SYN_RECV ->  TCP_ESTABLISHED

2.3  server通过listen操作开始监听,此时就可以接受到client连接请求。

listen ----> SYSCALL_DEFINE2(listen) -> __sys_listen -> sock->ops->listen --->  inet_csk_listen_start

2.4 accept

accept()实际要做的事件并不多,它的作用是返回一个已经建立连接的socket(即经过了三次握手),这个过程是异步的,accept()并不亲自去处理三次握手过程,而只是监听icsk_accept_queue队列,当有socket经过了三次握手,它就会被加到icsk_accept_queue中,所以accept要做的就是等待队列中插入socket,然后被唤醒并返回这个socket。而三次握手的过程完全是协议栈本身去完成的。换句话说,协议栈相当于写者,将socket写入队列,accept()相当于读者,将socket从队列读出。这个过程从listen就已开始,所以即使不调用accept(),客户仍可以和服务器建立连接,但由于没有处理,队列很快会被占满。

2.5 bind

bind操作的主要作用是将创建的socket与给定的地址相绑定,这样创建的服务才能公开的让外部调用。当然对于socket服务器的创建来说,这一步不是必须的,在listen()时如果没有绑定地址,系统会选择一个随机可用地址作为服务器地址。

linux kernel 三次握手建立TCP链接的实现相关推荐

  1. 计算机网络tcp三次握手分析,tcp三次握手及原理

    TCP/IP 是很多的不同的协议组成,实际上是一个协议组,TCP 用户数据报表协议(也 称作TCP 传输控制协议,Transport Control Protocol.可靠的主机到主机层协议.这里要先 ...

  2. TCP的三次握手(建立连接)和四次挥手(关闭连接)

    随心所意 博客园  :: 首页  :: 新随笔  :: 联系  :: 订阅   :: 管理 posts - 437, comments - 52, trackbacks - 0 公告 昵称:higir ...

  3. 27.Linux网络编程 掌握三次握手建立连接过程掌握四次握手关闭连接的过程掌握滑动窗口的概念掌握错误处理函数封装实现多进程并发服务器实现多线程并发服务器

    基本概念叫协议 什么叫协议? 协议是一个大家共同遵守的一个规则, 那么在这个网络通信当中,其实就是双方通信和解释数据的一个规则,这个概念 你也不用记,你只要心里明白就可以了, 分层模型, 物数网传会表 ...

  4. TCP三次握手建立连接的过程

    来源:TCP三次握手建立连接的过程 TCP 是面向连接的协议,所以每次发出的请求都需要对方进行确认.TCP 客户端与 TCP 服务器在通信之前需要完成三次握手才能建立连接. 下面详细讲解三次握手的过程 ...

  5. TCP的三次握手建立连接和四次握手释放连接

    1.socket中TCP的三次握手建立连接详解 我们知道tcp建立连接要进行"三次握手",即交换三个分组.大致流程如下: 客户端向服务器发送一个SYN J 服务器向客户端响应一个S ...

  6. TCP三次握手建立连接和四次挥手关闭连接

    TCP三次握手 是指建立TCP连接协议时,需要在客户端和服务器之间发送三个包,握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据. 第一次握手:客户端发送第一个包,其中S ...

  7. TCP网络编程-三次握手建立连接-四次挥手断开连接

    客户端与服务器进行TCP通信连接时,要进行三次握手建立连接. 客户端与服务器进行TCP断开连接时,要进行四次挥手断开连接.

  8. HTTP 三次握手  建立连接 和  四次握手断开连接

    三次握手建立连接  第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机: 第二次握手:主机B收到请求后要确认联 ...

  9. 以太网 TCP三次握手、TCP四次挥手详细介绍与报文简要分析。

    2.7.0 以太网 TCP协议(三次握手.四次挥手) 传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的.可靠的传输层通信协议. 面向连接:指使用TCP ...

最新文章

  1. typedef 函数指针
  2. oracle 恢复dmp文件时,创建 tablespace user
  3. 【数理知识】方程一阶二阶及常用词语含义
  4. 如何成为一位杰出的程序员
  5. 20155220 实验三 敏捷开发与XP实践 实验报告
  6. 【鉴轻尘】BTC的暴跌的是因为BCH的分叉,但是你知道为什么?
  7. vim emmet插件
  8. ZH奶酪:自然语言处理工具LTP语言云调用方法
  9. 为什么俺推荐Python「1」:作为脚本语言的Python
  10. vue根据身份证号算出年龄
  11. oracle查询时间段差,关于oracle数据库中进行查询的时候出现效率特别差的一种情况...
  12. 桌面扫码点餐系统(小程序+Java后台)
  13. 基于lio-sam框架,教你如何进行回环检测及位姿计算
  14. android11原生录屏,终于把安卓这项功能实现了!iOS 11录屏功能演示:超好用
  15. 概率机器人(Probability Robotics)笔记 Chapter 9: 占据栅格建图(Occupancy Grid Mapping)
  16. Windows 10环境中安装Snort+Barnyard2+MySQL
  17. idea使用Protobuf插件
  18. 清华大学计算机系2015分数线,清华大学2015年计算机系GCT成绩复试分数线及复试安排...
  19. JDK1.7绿色解压版64位
  20. 数字图像处理-图像基础-复习总结

热门文章

  1. Python基本类型-字典
  2. ​shell中经常能看到的:/dev/null 21
  3. html里面超链接alt_前端html--超链接,表格,表单属性
  4. 集群服务器分布式iis_集群,分布式,微服务,SOA概念
  5. python合并列表重新排序_python实现的合并两个排序的列表
  6. ubuntu MySQL安装指南
  7. linux脚本计算器加减乘除,用shell写一个简易计算器,可以实现加、减、乘、除运算,假如脚本名字为1.sh,执行示例:./1....
  8. flink读mysql速度怎么样_[DB] Flink 读 MySQL
  9. [蓝桥杯][2014年第五届真题]生物芯片(数论)
  10. c语言cin改scanf,我的代码用scanf输入wa了,改成cin就ac了 ?