第13章 TCP编程(2)_TCP的连接和关闭过程
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的连接和关闭过程的更多相关文章
- 第13章 TCP编程(1)_socket套接字
1. socket套接字 (1)套接字简介 ①socket是一种通讯机制,它包含一整套的调用接口和数据结构的定义,它给应用进程提供了使用如TCP/UDP等网络协议进行网络通讯的手段. ②Linux中的 ...
- 第13章 TCP编程(4)_基于自定义协议的多线程模型
7. 基于自定义协议的多线程模型 (1)服务端编程 ①主线程负责调用accept与客户端连接 ②当接受客户端连接后,创建子线程来服务客户端,以处理多客户端的并发访问. ③服务端接到的客户端信息后,回显 ...
- 第13章 TCP编程(3)_基于自定义协议的多进程模型
5. 自定义协议编程 (1)自定义协议:MSG //自定义的协议(TLV:Type length Value) typedef struct{ //协议头部 ];//TLV中的T unsigned i ...
- 五十五、linux 编程——TCP 连接和关闭过程及服务器的并发处理
55.1 TCP 连接和关闭过程 55.1.1 介绍 建立连接的过程就是三次握手的过程:客户端发送 SYN 报文给服务器,服务器回复 SYN+ACK 报文,客户机再发送 ACK 报文. 关闭连接的过程 ...
- TCP/IP协议的建立连接与关闭连接过程
一.建立连接(三次握手) 第一次握手:建立连接时,客户端发送SYN(seq=x)包到服务器,并进入SYN_SENT状态,等待服务器的确认.SYN:同步序列编号(Synchronize Sequence ...
- 【RL-TCPnet网络教程】第13章 RL-TCPnet之TCP服务器
第13章 RL-TCPnet之TCP服务器 本章节为大家讲解RL-TCPnet的TCP服务器实现,学习本章节前,务必要优先学习第12章TCP传输控制协议基础知识.有了这些基础知识之后,再搞本 ...
- 《Android开发艺术探索》读书笔记 (13) 第13章 综合技术、第14章 JNI和NDK编程、第15章 Android性能优化
第13章 综合技术 13.1 使用CrashHandler来获取应用的Crash信息 (1)应用发生Crash在所难免,但是如何采集crash信息以供后续开发处理这类问题呢?利用Thread类的set ...
- UNIX网络编程 第5章 TCP客户/服务器程序示例
UNIX网络编程 第5章 TCP客户/服务器程序示例
- 《Clojure编程》笔记 第13章 测试
目录 背景简述 第13章 测试 13.1 术语 13.2 clojure.test 13.2.1 定义测试的两种方式 13.2.1.1 用deftest宏把测试定义成单独的函数 13.2.1.2 用w ...
随机推荐
- vue-cli 添加到生产环境问题总结
1. 路径问题 部署到生产环境后的实际链接为: 服务器项目路径 + serviceUrl的路径 创建 GlobalConstant.js 分别配置 开发环境和生产环境的 路径 (注:此处生 ...
- Java一个简单的线程池实现
线程池代码 import java.util.List; import java.util.Vector; public class ThreadPool { private static ...
- BZOJ4899: 记忆的轮廓【概率期望DP】【决策单调性优化DP】
Description 通往贤者之塔的路上,有许多的危机. 我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增, 在[1,n]中,一共有n个节点.我 ...
- [转载]PHP 连接 Rabbitmq 实例代码
转自 http://www.dahouduan.com/2017/11/23/php-rabbitmq-demo/ 接下来我们用 php 连接 rabbitmq 玩一玩.还没有安装 rabbitmq ...
- 《DSP using MATLAB》Problem 4.4
- python list 的查找, 搜索, 定位, 统计
Python中是有查找功能的,四种方式:in.not in.count.index,前两种方法是保留字,后两种方式是列表的方法. 下面以a_list = ['a','b','c','hello'],为 ...
- 实习第二天-java参数传递-精华在文章最后2句话
对于基本类型的传递,我们很容易理解,而对于对象,总让人感觉是按引用传递,看下面的程序: public class ObjectRef { //基本类型的参数传递 public static void ...
- log4net保存到数据库系列五、新增数据库字段
园子里面有很多关于log4net保存到数据库的帖子,但是要动手操作还是比较不易,从头开始学习log4net数据库日志一.WebConfig中配置log4net 一.WebConfig中配置log4ne ...
- Entity Framework常用的查询方式
Entity Framework支持的查询方式有三种 LINQ to Entities Entity SQL Native SQL [LINQ to Entities] LINQ(语言集成查询)是从V ...
- java打jar包的几种方式详解
经常会头疼于一个jar包是如何制作的,包括maven的打包方式,springboot的打jar包的原理,jar包稍稍有错误就会完全无法运行.在网上折腾了很久终于有些思路和步骤,在这里做个笔记 本文目录 ...