【Unix网络编程】TCP三次握手,四次挥手,TCP状态转换图以及各个api之间的关系

tcp最重要的就是3次握手和4次挥手,但是我们编程的api和3次握手4次挥手有什么关系,这篇文章带你好好梳理一下

首先先来看看tcp3次握手4次挥手的状态转换图,简单版的详细版的

1、简单版:

181351206012825.png

三次握手:正常的客户端连接服务器,首先就是发送一个syn的包给服务器表示请求连接服务器,然后服务器回复一个表示服务器已经准备好的ack(客户端syn+1)和一个syn,客户端也回复一个ack表示客户端也准备好了,这时3次握手完成,客户端和服务器进入连接建立的状态,可以进行收发数据

 

四次挥手:当客户端主动关闭连接时,会先发送一个fin给服务器,服务器接收到fin后也发送一个确认号ack给客户端,这是客户端这一端就关闭了(这时客户端就不会收发数据了,能接受服务器发送过来的数据,tcp是全双工的,需要一端一端的关闭),然后服务器处理完业务过后,想要关闭了,也发送一个fin给客户端,客户端收到后发送一个ack给服务器,表示ok,至此,该连接关闭

 

 为什么要进行三次握手,四次挥手呢?

首先要知道我们网络的 发送的报文可能因为网络状况丢失,或者不按时到达

为什么要三次握手,我们假设tcp协议的连接建立是2次握手会怎么样?

假如2次握手连接就已经建立的话,如果在网络中存在一个已经失效的请求报文到达服务器(可能是之前客户端超时重发的) ,那服务器接收到syn后会发送ack给客户端,并且认为连接已经建立,就往客户端发送数据,那这时客户端根本就没有响应,因为连接根本没有建立,只是服务器一厢情愿的认为,服务器就会一直等 ,浪费资源

 为什么要四次挥手呢?

因为关闭连接时,发送fin给对端,只是表示本端不再发送数据了,但是仍然能够接收对端发送来的数据,tcp连接时全双工的,双方都能够发送数据,当发送fin,接收到ack时,只关闭了一端,这时候时半双工状态, 另外一端不再发送数据也要关闭时,再发送fin对端,所以通常要进行4次挥手

在unix网络编程卷1中说到,第一次发送的fin时可能随发送的数据一起发送的。而且服务器回复的ack和fin都出自执行被动关闭的一端,是有可能被合并为一个分节,一次发送的,所以说关闭连接时“通常”是四次挥手

 

2、详细版:

preview

观察详细 状态图的实线部分,就是正常的客户端的状态转换,虚线部分是正常的服务器的状态转换,执行主动关闭连接的 一端(这里指客户端发送fin主动关闭连接)进入time_wait状态,时间长达2MSL(MSL:最长分节生命期maximum segment lifetime,是任何IP数据报能够在网络中存活的最长时间)

为什么会 进入time_wait状态呢?

1)tcp是可靠的全双工连接,需要保证连接正常的终止

 假设最后服务器发送的fin客户端收到了,然后客户端发送给服务器的ack丢失在网络中了,服务器没有接收到最终的ack,触发超时重传机制,重新发送了一个fin给客户端,客户端这时接收到重传的fin,就会重新发送ack给服务器,这个时间段客户端需要维护之前的状态信息,如果客户端不维护之前的状态信息,就是响应一个RST(表示重置),会被服务器认为这是一个错误,这就是tcp为了保证全双工连接两端都正常关闭的原因

2)tcp允许老的重复的分节在网络中消逝

首先要知道tcp协议中,time_wait状态下的连接不允许重新新建连接,假如客户端程序调用close关闭连接后退出程序,这时客户端处于 time_wait状态,然后立即重启这个客户端(相同的ip和端口,5元组确认一条连接(源、目的IP,源、目的端口,协议)),发送syn给服务器,tcp不允许time_wait下再新建连接,所以这个syn会消亡在网络中(2msl保证包能正常的消逝)

我们在这里假设没有time_wait的状态,关闭了老的连接,立即就建立了一个新的连接,tcp的协议栈是没法区别这是两条连接(因为5元组相同), 他会认为是同一条连接, 如果老的连接之前的包在网络中姗姗来迟,那会被认为是新的连接的数据包,就会发送给应用层,就会造成混乱的情况,有了time_wait 状态并持续2msl,就会让 某个方向上的分组最多存活msl秒被丢弃, 另一个 方向的应答最多存活msl秒被丢弃,这样就能保证每成功建立一个tcp连接,老的重复分组都已在网络中消逝

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目 录 译者序 前言 第一部分 TCP事务协议 第1章 T/TCP概述 1 1.1 概述 1 1.2 UDP上的客户-服务器 1 1.3 TCP上的客户-服务器 6 1.4 T/TCP上的客户-服务器 12 1.5 测试网络 15 1.6 时间测量程序 15 1.7 应用 17 1.8 历史 19 1.9 实现 20 1.10 小结 21 第2章 T/TCP协议 23 2.1 概述 23 2.2 T/TCP中的新TCP选项 23 2.3 T/TCP实现所需变量 25 2.4 状态变迁 27 2.5 T/TCP的扩展状态 28 2.6 小结 30 第3章 T/TCP使用举例 31 3.1 概述 31 3.2 客户重新启动 31 3.3 常规的T/TCP事务 33 3.4 服务器收到过时的重复SYN 34 3.5 服务器重启动 35 3.6 请求或应答超出报文段最大长度MSS 36 3.7 向后兼容性 39 3.8 小结 41 第4章 T/TCP协议(续) 43 4.1 概述 43 4.2 客户的端口号和TIME_WAIT状态 43 4.3 设置TIME_WAIT状态的目的 45 4.4 TIME_WAIT状态的截断 48 4.5 利用TAO跳过三次握手 51 4.6 小结 55 第5章 T/TCP协议的实现:插口层 56 5.1 概述 56 5.2 常量 56 5.3 sosend函数 56 5.4 小结 58 第6章 T/TCP的实现:路由表 59 6.1 概述 59 6.2 代码介绍 59 6.3 radix_node_head结构 60 6.4 rtentry结构 61 6.5 rt_metrics结构 61 6.6 in_inithead函数 61 6.7 in_addroute函数 62 6.8 in_matroute函数 63 6.9 in_clsroute函数 63 6.10 in_rtqtimo函数 64 6.11 in_rtqkill函数 66 6.12 小结 69 第7章 T/TCP实现:协议控制块 70 7.1 概述 70 7.2 in_pcbladdr函数 71 7.3 in_pcbconnect函数 71 7.4 小结 72 第8章 T/TCP实现: TCP概要 73 8.1 概述 73 8.2 代码介绍 73 8.3 TCP的protosw结构 74 8.4 TCP控制块 74 8.5 tcp_init函数 75 8.6 tcp_slowtimo函数 75 8.7 小结 76 第9章 T/TCP实现:TCP输出 77 9.1 概述 77 9.2 tcp_output函数 77 9.2.1 新的自动变量 77 9.2.2 增加隐藏的状态标志 77 9.2.3 在SYN_SENT状态不要重传SYN 78 9.2.4 发送器的糊涂窗口避免机制 78 9.2.5 有RST或SYN标志时强制发送报文段 79 9.2.6 发送MSS选项 80 9.2.7 是否发送时间戳选项 80 9.2.8 发送T/TCP的CC选项 80 9.2.9 根据TCP选项调整数据长度 83 9.3 小结 83 第10章 T/TCP实现:TCP函数 84 10.1 概述 84 10.2 tcp_newtcpcb函数 84 10.3 tcp_rtlookup函数 85 10.4 tcp_gettaocache函数 86 10.5 重传超时间隔的计算 86 10.6 tcp_close函数 89 10.7 tcp_msssend函数 90 10.8 tcp_mssrcvd函数 91 10.9 tcp_dooptions函数 96 10.10 tcp_reass函数 98 10.11 小结 99 第11章 T/TCP实现:TCP输入 101 11.1 概述 101 11.2 预处理 103 11.3 首部预测 104 11.4 被动打开的启动 105 11.5 主动打开的启动 108 11.6 PAWS:防止序号重复 114 11.7 ACK处理 115 11.8 完成被动打开和同时打开 115 11.9 ACK处理(续) 116 11.10 FIN处理 118 11.11 小结 119 第12章 T/TCP实现:TCP用户请求 120 12.1 概述 120 12.2 PRU_CONNECT请求 120 12.3 tcp_connect函数 120 12.4 PRU_SEND和PRU_SEND_EOF请求 124 12.5 tcp_usrclosed函数 125 12.6 tcp_sysctl函数 126 12.7 T/TCP的前景 126 12.8 小结 127 第二部分 TCP的其他应用 第13章 HTTP:超文本传送协议 129 13.1 概述 129 13.2 HTTP和HTML概述 130 13.3 HTTP 132 13.3.1 报文类型:请求与响应 132 13.3.2 首部字段 133 13.3.3 响应代码 133 13.3.4 各种报文头举例 134 13.3.5 例子:客户程序缓存 135 13.3.6 例子:服务器重定向 136 13.4 一个例子 136 13.5 HTTP的统计资料 138 13.6 性能问题 139 13.7 小结 141 第14章 在HTTP服务器上找到的分组 142 14.1 概述 142 14.2 多个HTTP服务器 144 14.3 客户端SYN的到达间隔时间 145 14.4 RTT的测量 149 14.5 用listen设置入连接队列的容量 150 14.6 客户端的SYN选项 154 14.7 客户端的SYN重传 156 14.8 域名 157 14.9 超时的持续探测 157 14.10 T/TCP路由表大小的模拟 160 14.11 mbuf的交互 162 14.12 TCP的PCB高速缓存和首部预测 163 14.13 小结 165 第15章 NNTP:网络新闻传送协议 166 15.1 概述 166 15.2 NNTP 167 15.3 一个简单的新闻客户 170 15.4 一个复杂的新闻客户 171 15.5 NNTP的统计资料 172 15.6 小结 173 第三部分 Unix域协议 第16章 Unix域协议:概述 175 16.1 概述 175 16.2 用途 176 16.3 性能 177 16.4 编码举例 177 16.5 小结 179 第17章 Unix域协议:实现 180 17.1 概述 180 17.2 代码介绍 180 17.3 Unix domain和protosw结构 181 17.4 Unix域插口地址结构 182 17.5 Unix域协议控制块 183 17.6 uipc_usrreq函数 185 17.7 PRU_ATTACH请求和unp_attach函数 186 17.8 PRU_DETACH请求和unp_detach函数 187 17.9 PRU_BIND请求和unp_bind函数 189 17.10 PRU_CONNECT请求和unp_connect 函数 191 17.11 PRU_CONNECT2请求和unp_connect2 函数 195 17.12 socketpair系统调用 198 17.13 pipe系统调用 202 17.14 PRU_ACCEPT请求 203 17.15 PRU_DISCONNECT请求和 unp_disconnect函数 204 17.16 PRU_SHUTDOWN请求和unp_shutdown 函数 205 17.17 PRU_ABORT请求和unp_drop函数 206 17.18 其他各种请求 207 17.19 小结 209 第18章 Unix域协议:I/O和描述符的传递 210 18.1 概述 210 18.2 PRU_SEND和PRU_RCVD请求 210 18.3 描述符的传递 214 18.4 unp_internalize函数 218 18.5 unp_externalize函数 220 18.6 unp_discard函数 221 18.7 unp_dispose函数 222 18.8 unp_scan函数 222 18.9 unp_gc函数 223 18.10 unp_mark函数 230 18.11 性能(再讨论) 231 18.12 小结 231 附录A 测量网络时间 232 附录B 编写T/TCP应用程序 242 参考文献 246 缩略语 251

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值