传输层(一)TCP的三次握手和四次挥手及关闭套接字的原理

TCP连接需三次握手才能建立,断开连接则需要四次握手。

  客户端TCP状态迁移:
  CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
  服务器TCP状态迁移:
  CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED

  整个过程如下图所示:

  一、建立TCP连接

  三次握手:所谓的“三次握手”即对每次发送的数据量是怎样跟踪进行协商使数据段的发送和接收同步,根据所接收到的数据量而确定的数据确认数及数据发送、接收完毕后何时撤消联系,并建立虚连接。

  为了提供可靠的传送,TCP在发送新的数据之前,以特定的顺序将数据包的序号,并需要这些包传送给目标机之后的确认消息。TCP总是用来发送大批量的数据。当应用程序在收到数据后要做出确认时也要用到TCP。

  位码即TCP标志位,有6种标示:SYN(synchronous建立联机)、ACK(acknowledgement确认)、PSH(push传送) 、FIN(finish结束)、RST(reset重置)、URG(urgent紧急)

  确认号:其数值等于发送方的发送序号 +1(即接收方期望接收的下一个序列号)。

  详细过程如下:

  第一次:

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

  第二次:

  第二次握手:服务器收到SYN包,必须确认客户的SYN(ACK=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。

  第三次:

  第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

  三次握手的流程图如下:

  在三次握手过程中,还有一些重要概念:

  未连接队列:

 
 在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(SYN=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发
出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于
SYN_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。

  Backlog参数:

  表示内核为相应套接字排队的最大连接个数。仅对于backlog来说,我们需要取一个比较大的值以应对大量的服务请求。

  服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。

  半连接存活时间

  是指半连接队列的条目存活的最长时间,也即服务器从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间。

  二、关闭TCP连接:

  由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个FIN只意味着

这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

  TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。

  步骤如下:

  第一步:当主机A的应用程序通知TCP数据已经发送完毕时,TCP向主机B发送一个带有FIN附加标记的报文段(FIN表示英文finish)。

  第二步:主机B收到这个FIN报文段之后,并不立即用FIN报文段回复主机A,而是先向主机A发送一个确认序号ACK,同时通知自己相应的应用程序:对方要求关闭连接(先

发送ACK的目的是为了防止在这段时间内,对方重传FIN报文段)。

  第三步:主机B的应用程序告诉TCP:我要彻底的关闭连接,TCP向主机A送一个FIN报文段。

  第四步:主机A收到这个FIN报文段后,向主机B发送一个ACK表示连接彻底释放。

  在网络编程时,常常会创建套接字,套接字使用完成后常常关闭套接字,那么关闭Socket时客户端和服务端究竟做了什么?

  关闭socket分为主动关闭(Active closure)和被动关闭(Passive closure)两种情况。

  主动关闭是指有本地主机主动发起的关闭;而被动关闭则是指本地主机检测到远程主机发起关闭之后,作出回应,从而关闭整个连接。

  被动关闭的情况下:

  客户端发起中断连接请求,也就是发送FIN报文。

  服务器接到FIN报文后,报文意思是说“我客户端没有数据要发给你了,但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据”。

  所以服务器先发送ACK,告诉客户端:“你的请求我收到了,但是我还没准备好,请继续你等我的消息"。

  这个时候客户端就进入FIN_WAIT状态,继续等待服务器的FIN报文。

  当服务器确定数据已发送完成,则向客户端发送FIN报文,告诉客户端:“好了,我这边数据发完了,准备好关闭连接了"。

  Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕服务器不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果服务器没有收

到ACK则可以重传“。

  Server端收到ACK后,"就知道可以断开连接了"。

  Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。就这样,TCP连接就这样关闭了!

  MSL意思是最大段生命周期(Maximum Segment Lifetime)表明一个包存在于网络上到被丢弃之间的时间。每个IP包有一个TTL(time_to_live),当它减到0时则包被丢弃。

每个路由器使TTL减一并且传送该包。当一个程序进入TIME_WAIT状态时,他有2个MSL的时间,这个充许TCP重发最后的ACK,万一最后的ACK丢失了,使得FIN被重新传输。

在2MSL等待状态完成后,socket进入CLOSED状态。

  整个过程客户端所经历的状态如下:

  而服务器所经历的过程如下:

  注意: 在TIME_WAIT状态中,如果TCP client端最后一次发送的ACK丢失了,它将重新发送。TIME_WAIT状态中所需要的时间是依赖于实现方法的。典型的值为30秒、1分钟和2分钟。等待之后连接正式关闭,并且所有的资源(包括端口号)都被释放。

  问题1:为什么连接的时候是三次握手,关闭的时候却是四次握手?
  因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同
步的。但是关闭连接时,当Server端

收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你
发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我

才能发送FIN报文,因此不能一起发送。故需要四步握手。

  问题2:为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

  虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发

可能丢失的ACK报文。

  三、winsocks2关闭套接字的函数有:closesocket,shutdown,WSASendDisconnect.。

  int closesocket( SOCKET s)的作用是关闭指定的socket,并且回收其所有的资源。

  int shutdown( SOCKET s,  int how)则是用于任何类型的套接口禁止接收、禁止发送或禁止收发,但并不对资源进行回收。

  how参数为0时,则该套接口上的后续接收操作将被禁止。这对于低层协议无影响。

  how为1时,则禁止后续发送操作。对于TCP,将发送FIN。

  how为2时,则同时禁止收和发。

时间: 05-06

传输层(一)TCP的三次握手和四次挥手及关闭套接字的原理的相关文章

TCP的三次握手和四次挥手与路由器(三层)转发原理

传输层是国际标准化组织提出的开放系统互连(OSI)参考模型中的第四层.该层协议为网络端点主机上的进程之间提供了可靠.有效的报文传送服务.其功能紧密地依赖于网络层的虚拟电路或数据报服务.传输层定义了主机应用程序之间端到端的连通性.传输层只存在于端开放系统中,是介于低3层通信子网系统和高3层之间的一层,但是很重要的一层,因为它是源端到目的端对数据传送进行控制从低到高的最后一层.传输层的服务一般要经历传输连接建立阶段,数据传送阶段,传输连接释放阶段3个阶段才算完成一个完整的服务过程.而在数据传送阶段又

TCP的三次握手与四次挥手

最近在看一些Tcp网络编程方面的内容,不免涉及客户端和服务器交互的内容,其中最经典的应该是TCP的三次握手和四次挥手了. 背景描述 通过上一篇中网络模型中的IP层的介绍,我们知道网络层,可以实现两个主机之间的通信.但是这并不具体,因为,真正进行通信的实体是在主机中的进程,是一个主机中的一个进程与另外一个主机中的一个进程在交换数据.IP协议虽然能把数据报文送到目的主机,但是并没有交付给主机的具体应用进程.而端到端的通信才应该是应用进程之间的通信. UDP,在传送数据前不需要先建立连接,远地的主机在

C/S架构,osi五层协议,TCP的三次握手与四次挥手

1.C/S B/S架构 C:client 客户端 B:Browser 浏览器 S:server 服务端 C/S 客户端与服务器之间的架构:QQ,微信,游戏,App的都属于C/S架构 优点:安全性高,个性化设置,功能全面,响应速度快 缺点:开发成本高,维护成本高,面向的客户固定 B/S 浏览器与服务器之间的架构:属于C/S架构,最近几年比较流行的特殊的C/S架构 优点:开发维护成本低,面向用户广泛 缺点:安全性相对低,响应速度相对慢,个性化的设置单一 2.互联网通信的原理 1.物理连接介质将两台电

TCP/IP三次握手与四次挥手的正确姿势

A 理解TCP/IP三次握手与四次挥手的正确姿势https://www.cnblogs.com/lms0755/p/9053119.html B 四次挥手过程理解 https://blog.csdn.net/qq_38950316/article/details/81087809 C TCP三次握手四次挥手详解http://www.cnblogs.com/zmlctt/p/3690998.html 原文地址:https://www.cnblogs.com/kelelipeng/p/1021678

TCP 的三次握手 与 四次挥手详解(转载)

建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源.Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了. 那如何断开连接呢?简单的过程如下: [注意]中断连接端可以是Client端,也可以是Server端. 假设Client端发起中断连接请求,也就是发送FIN报文.Server端接到FIN报文后,

理解TCP/IP三次握手与四次挥手的正确姿势

背景 和女朋友异地恋一年多,为了保持感情我提议每天晚上视频聊天一次. 从好上开始,到现在,一年多也算坚持下来了. 问题 有时候聊天的过程中,我的网络或者她的网络可能会不好,视频就会卡住,听不到对方的声音,过一会儿之后才会恢复. 中间双方可能就要不断的确认网络是否恢复,但是有时候会: 她:"你可以听到了吗?" 我:"可以了,你呢?". 她:"喂喂,你可以听到了吗?" 我:"可以了,我可以听到了,你呢?" 她:"你可以听

TCP的三次握手、四次挥手--非常详细讲解

TCP(Transmission Control Protocol) 传输控制协议 1?TCP三次握手和四次挥手的过程图 tcp的6种标志位的分别代表: SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急) Sequence number(顺序号码) Acknowledge number(确认号码) 客户端TCP状态迁移:CLOSED->SYN_SENT-

TCP的三次握手与四次挥手(个人总结)

序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生:给字节编上序号后,就给每一个报文段指派一个序号:序列号seq就是这个报文段中的第一个字节的数据编号. 确认号ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号:序列号表示报文段携带数据的第一个字节的编号:而确认号指的是期望接收到下一个字节的编号:因此当前报文段最后一个字节的编号+1即为确认号. 确认ACK:占1位,仅当ACK=1时,确认号字段才有效.AC

TCP的三次握手与四次挥手理解及面试题(很全面)

序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生:给字节编上序号后,就给每一个报文段指派一个序号:序列号seq就是这个报文段中的第一个字节的数据编号. 确认号ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号:序列号表示报文段携带数据的第一个字节的编号:而确认号指的是期望接收到下一个字节的编号:因此当前报文段最后一个字节的编号+1即为确认号. 确认ACK:占1位,仅当ACK=1时,确认号字段才有效.AC