4. TCP的连接和关闭过程

4.1 TCP连接的三次握手和四次挥手

(1)三次握手

  ①第1次握手:建立连接。客户端发送连接请求报文段(SYN=1,sequence Number=x);然后客户端进入SYN_SEND状态,等待服务器确认。

  ②第2次握手:服务器收到SYN报文段,然后对SYN报文段进行确认,并设置(Acknowlegement Number为x+1)。同时,自己还要发送SYN请求信息。上述信息放到一个报文段(SYN+ACK)中,一并发送给客户端,此时服务器进入SYN_RECV状态。

  ③第3次握手:客户端收到服务器的SYN+ACK报文段。然后将ACK设置为y+1,向服务器发送ACK报文,这个报文段发送完以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP的三次握手。

(2)四次挥手

  ①第1次挥手:客户端(也可以是服务端)设置seq和ACK,向服务器发送一个FIN报文段。此时,客户端进入FIN_WAIT_1状态,表示客户端没有数据要发送给服务器了。

  ②第2次挥手:服务器收到客户端发送的FIN报文段,向客户端回一个ACK报文,客户端收到后进入FIN_WAIT_2状态;表示服务端收到客户端的关闭请求,但服务端可能还有数据没发完,让客户端继续等服务端的通知。

  ③第3次挥手:服务器向客户端发送FIN报文,表示服务端数据己发送完毕,可以关闭连接。同时服务器进入LAST_ACK状态。

  ④第4次挥手:客户端收到服务器发送的FIN报文,向服务器发送ACK报文,然后客户端进入TIME_WAIT状态。服务器收到客户端的ACK报文段后,就关闭连接。此时,客户端等待2MSL后就关闭连接了。

4.2 为什么要三次握手

(1)可防止己失效的连接请求报文突然又传递到服务端

  ①假设Client发出第1个连接请求报文段并没有丢失,而是在某个网络结点长时间滞留,以致延误到以后的某个时间才到达Server。但这时客户端己经因超时重发一个连接请求报文段给Server,并正常建立了连接。

  ②如果采用两次握手,那么当这个延迟的连接请求到达时,服务端只需发送一个确认,新的连接就会在服务端建立起来。但客户端收到这个确认,它会认为自己并没有发出请求(因为该请求己失效!),因此就不会理会服务端的确认,也不会向服务端发送数据,而服务端则认为新的连接己经建立了,就一直等待客户端发送数据,直到超出保活计时器设置值才判断客户端出了问题,这样无形中就会浪费服务器的资源。

  ③而如果采用3次握手,服务端收到延迟的连接请求(第1次握手)并向客户端发送确认,但客户端收到这个确认时(第2次握手),同样并不会理会它,因此也就不会与服务端进行第3次握手。由于采用三次握手机制,这时服务端因没握过第3次手,所以并不会建立连接。这样就可以解决失效请求突然到达的问题。

(2)可靠性的理解

  ①世界上不存在完全可靠的通信协议。当A发送一个请求给B时,为了保证可靠性,B需要给A发一个己收到请求的确认包,但B的这个确认包是否到达A,需要A发送一个确认的确认给B,而这个确认B是否收到,仍需要B发给A一个确认,如此无休止去确认下去…。因此,从理论上无法做到完全的可靠,一般只需3次握手即可保证有较高的可靠性。

  ②“三次握手”是点对点通信的一般规则,但即使三次握手成功,也只能说明之前的通信条件和环境,而不能决定和预测之后的通信环境。根据经验,两个端点通信失败,最大的可能性是端点本身的故障,而三次握手成功排除了这种可能(见后面4.4中对讲机的例子)。以后的情况很难预测。通信协议只能做到尽可能的可靠,而不能做到理论上的完全可靠。

  ③由于TCP是面向连接的,无论哪一方向另一方发送数据,都必须在双方之间建立一个可靠的连接。

4.3 为什么需要4次挥手

(1)发起中断连接可以是客户端也可以是服务端。假设这里由客户端发起。当发送FIN报文时,表示“我(Client)没有数据要发给你了”。但如果你有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。

(2)服务端收到客户端的FIN报文后,先发送一个ACK,用于告诉客户端:“你的请求我收到了,但我还没准备好,请你继续等我的消息”。这时客户端进入FIN_WAIT_1状态,继续等待Server端的FIN报文。

(3)当服务端确定数据己发送完毕,则向Client端发送FIN报文,告诉Client端,好了,我(Server)这边的数据己发送完结了,准备好关闭连接了。

(4)客户端收到服务端的FIN报文后,就知道可以关闭连接了。但服务端并不知道客户端收到这个FIN报文没有,因此客户端要发送最后一个ACK报文,以便告知服务器己收到FIN,如果服务器收到这个ACK,就可以关闭连接。但现在客户端并不急着马上关闭连接,因为最后一个ACK可能丢失,所以客户端要等2MSL(2倍的最大报文生存时间)的时间,如果这期间没有收到服务器的信息,说明服务器己经关闭,否则需重发最后的那个ACK报文。

4.4 生活中的例子

(1)对讲机的三次握手

  ①C→S:“喂,你听得到吗?”(C ->SYN_SEND)

  ②S→C:“听到,你听得到我吗?”(应答与请求同时发出,S->SYN_RCVD | C ->ESTABLISHED。注意:第2次握手,能说明C的发和S的收都没问题)。

  ③C→S:“能听到,今天balabala……”(S->ESTABLISHED。注意:第3次握手能说明C的收和S的发也没问题。到此TCP的双工模式被证明能正常工作!)

(2)四次挥手

  ①C→S:“喂,我不说了。”(C→FIN_WAIT1)

  ②S→C:“我知道了。等下,上一句还没说完。Balabala…..”(S→CLOSE_WAIT && C→FIN_WAIT2)

  ③S→C:好了,说完了,我也不说了。”(S→LAST_ACK)

  ④C→S:我知道了。” S关闭连接,C等待S收到了消息(时长:2MSL),如果这段时间S无回应,说明S己关闭。否则重说一次”我知道了”给S端。(C→TIME_WAIT && S→CLOSED,最后C→CLOSED)

第13章 TCP编程(2)_TCP的连接和关闭过程的更多相关文章

  1. 第13章 TCP编程(1)_socket套接字

    1. socket套接字 (1)套接字简介 ①socket是一种通讯机制,它包含一整套的调用接口和数据结构的定义,它给应用进程提供了使用如TCP/UDP等网络协议进行网络通讯的手段. ②Linux中的 ...

  2. 第13章 TCP编程(4)_基于自定义协议的多线程模型

    7. 基于自定义协议的多线程模型 (1)服务端编程 ①主线程负责调用accept与客户端连接 ②当接受客户端连接后,创建子线程来服务客户端,以处理多客户端的并发访问. ③服务端接到的客户端信息后,回显 ...

  3. 第13章 TCP编程(3)_基于自定义协议的多进程模型

    5. 自定义协议编程 (1)自定义协议:MSG //自定义的协议(TLV:Type length Value) typedef struct{ //协议头部 ];//TLV中的T unsigned i ...

  4. 五十五、linux 编程——TCP 连接和关闭过程及服务器的并发处理

    55.1 TCP 连接和关闭过程 55.1.1 介绍 建立连接的过程就是三次握手的过程:客户端发送 SYN 报文给服务器,服务器回复 SYN+ACK 报文,客户机再发送 ACK 报文. 关闭连接的过程 ...

  5. TCP/IP协议的建立连接与关闭连接过程

    一.建立连接(三次握手) 第一次握手:建立连接时,客户端发送SYN(seq=x)包到服务器,并进入SYN_SENT状态,等待服务器的确认.SYN:同步序列编号(Synchronize Sequence ...

  6. 【RL-TCPnet网络教程】第13章 RL-TCPnet之TCP服务器

    第13章      RL-TCPnet之TCP服务器 本章节为大家讲解RL-TCPnet的TCP服务器实现,学习本章节前,务必要优先学习第12章TCP传输控制协议基础知识.有了这些基础知识之后,再搞本 ...

  7. 《Android开发艺术探索》读书笔记 (13) 第13章 综合技术、第14章 JNI和NDK编程、第15章 Android性能优化

    第13章 综合技术 13.1 使用CrashHandler来获取应用的Crash信息 (1)应用发生Crash在所难免,但是如何采集crash信息以供后续开发处理这类问题呢?利用Thread类的set ...

  8. UNIX网络编程 第5章 TCP客户/服务器程序示例

    UNIX网络编程 第5章 TCP客户/服务器程序示例

  9. 《Clojure编程》笔记 第13章 测试

    目录 背景简述 第13章 测试 13.1 术语 13.2 clojure.test 13.2.1 定义测试的两种方式 13.2.1.1 用deftest宏把测试定义成单独的函数 13.2.1.2 用w ...

随机推荐

  1. 使用Git进行本地提交后,未上传提交,却不小心删除了本地提交或提交所在分支,怎么办?????

    使用Git进行本地提交后,未上传提交,却不小心删除了本地提交或提交所在分支,怎么办????? 不要紧!!!! 可以使用git reflog命令来帮助恢复删除的本地提交! 运行以下命令你就知道怎么用了! ...

  2. spark 与 Hadoop 融合后 Neither spark.yarn.jars nor spark.yarn.archive is set

    参考文献: http://blog.csdn.net/lxhandlbb/article/details/54410644 每次提交Spark任务到yarn的时候,总会出现uploading reso ...

  3. word-如何将文字设置为插入超链接

    前言 使用word有时候想要将文字部分设置为插入超链接,本文对此进行介绍. 操作步骤 1. 输入需要插入链接的文字部分: 2. 选中文字部分单击右键,点击超链接进行插入: 具体操作如下图所示: 参考 ...

  4. Softmax回归介绍

    把输入值当成幂指数求值,再正则化这些结果值.这个幂运算表示,更大的证据对应更大的假设模型(hypothesis)里面的乘数权重值.反之,拥有更少的证据意味着在假设模型里面拥有更小的乘数系数.假设模型里 ...

  5. git中的needs merge问题

    这个问题是在先“储藏”起来了,后面再调用出来出现的错误. 解决的方法就是通过git add    ,git commit -m  提交上去就可以了.

  6. xdoj-1149(多重集合+容斥原理+组合数取模)

    #include <iostream> #include <algorithm> #include <cstdio> using namespace std; ty ...

  7. redis sentinel 高可用(HA)方案部署,及python应用示例

    redis sentinel(哨兵)高可用集群的部署方法,并通过 python 程序实例讲解如何使用 redis sentinel 简介 介绍 redis sentinel(哨兵)集群的部署,配置一主 ...

  8. Android USB gadget框架学习笔记

    一 Gadget框架结构 kernel/drivers/usb/gadget,这个目录是android下usbgadget的主要目录. Gadget功能组织单元:主要文件android.c,usb g ...

  9. openresty 使用cuid 类库生成短链接id

    cuid 是一个不错的id 生成算发,类似的有shortid .hashid 演示使用lua 包集成openresty 做测试 使用docker-compose 运行 dockerfile FROM ...

  10. JMeter:生成漂亮的多维度的HTML报告

    JMeter:生成漂亮的多维度的HTML报告我们做性能测试的时候会经常使用一些性能测试工具,我个人比较喜欢Jmeter这个工具,但是JMeter这个工具在生成测试报告方面一直有所欠缺.但是JMeter ...