TCP的三次握手
TCP报文
- 在学习本文可以先把TCP、IP 详解 02 先大致的看一下。
- 我们要想很好的理解三次握手的过程,我们要对TCP报文头有一个很清晰的理解,在这个理解的基础上在去学习我们的三次握手就很轻松了。
- TCP的报文信息如下所示:
源端口和目的端口
- 为了区分某台主机上具体某个应用 ip层的ip可以标识具体哪个主机,tcp的端口号标识具体哪个应用
序列号(SeqNum)
- Tcp连接中传输的字节流中的每一个字节都是按照顺序进行编号的,举个例子:如果一个报文中序列号为50,携带的数据为100个字段,那么下一个的序列号就应该100 + 50 + 1 = 151,保证了消息的完整性和正确性
确认号(ACK)
- 期望收到对方下一个报文第一个数据字节的序列号,例如B收到A发送过来的报文,其序列号为301,数据的长度为200字节,表面了B收到了A到序列为301 + 200 -1 = 500的数据,因此B希望收到A的下一个序列号为501,使用B发送给A的确认报文段的确认号为501
偏移量(offset)
- 偏移量 因为头部有可选字段长度不固定,它指出TCP的报文的数据距TCP的起始处有多远
保留域(Reserved)
- 保留域 一般不经常使用经常被标为0
控制位(Tcp Tags)
一般都八个控制位,我们对比较重要的六个进行讲解。
- URG : 紧急指针标志 1 标识紧急指针有效 0 标识负略紧急指针
- ACK : 确认序号标志 1 标识确认号有效 0 标识确认号无效
- PSH : push标志 1 标识含有push标识的数据,指示接收方接受到该报文之后应尽快将报文段交给应用程序而不是在缓冲区排队
- RST : 重置连接标志 1 用于重置可能由于主机奔溃而出现错误连接或者拒绝非法的报文段,拒绝连接请求
- SYN : 同步序号,用于建立连接过程 SYN =1 ACK = 0 说明该数据段没有使用稍带的确认域,SYN = 1 ACK = 1 标识连接应答稍带一个确认
- FIN : finish标志,用于释放连接
滑动窗口(Window)
- 用于告诉发送端和接受端缓存的大小,以此控制发送端发送数据的速率从而达到流量控制的功能。
检验合(checkSum)
- 指的基偶校验,包括对TCP报文段和TCP头部以16位进行计算所得,由发送端进行计算和存储,接收端进行验证。
紧急指针
- 只有控制位中的URG为1 的时候才有效。指出本报文段中紧急字节数
TCP可选项
- 定义一些其他的一些可选参数
TCP三次握手
- 我们在了解清楚上面的一些概念的时候,我们在看一下TCP的三次握手
- 当一个应用程序希望通过TCP和另外一个应用程序进行通讯的时候,会发送一个通讯的请求,请求必须被发送到一个确切的地址,在双方握手之后TCP会在两个应用程序之间建立一个全双工的通讯(全双工:互相都可以发消息)。
- 整体的流程如下所示;
如果图示文字不清晰可以参考以下文字:
- A和B首次进行通信,默认都是状态都是关闭的,客户端A主动打开,服务B被动打开
- 服务B的TCP服务器进程先创建传输控制块TCB(Transmission Control Block 传输控制器 存储了每个连接中的一些重要信息,如:TCP连接表,到发送和接收缓存的指针,到重传队列的指针,当前的发送和接受序号,等),准备接收客户进程的连接请求,然后服务器进程就处于LISTEN状态,等待客户的连接请求.如有,就做出响应
- 服务A也会创建一个传输控制块TCB然后想服务端B发送连接请求报文,报文包含同步位SYN=1,同时选择一个初始序号seq=x 这个x可以任意一个正整数,此时的报文段称之为SYN报文段,是不能携带任何数据的,但是会消耗一个序号。同时客户端A进入了一个同步已经发送的状态(SYN_SENT),这便是第一次握手的过程。
- 服务端B 接受到请求报文的时候如果同意连接,则发送确认报文(SYN = 1 ACK = 1 seq = y ack = x+1 ) 在确认报文段中,应把服务端的SYN和ACK位都置1,确认号是ack=x+1,因为服务端在发送请求的时候已经消耗了一个序列号,所以期望的序列号应该为x+1 ,同时也为自己选择一个初始序号seq=y。这个报文段也不能携带数据,同样要消耗一个序号。这时TCP服务器进程进入同步收到(SYN-RCVD)状态.
- TCP客户进程收到B的确认后,还要向B给出确认。确认报文段的ACK置1,确认号ack=y+1,而自己的序号seq=x+1。TCP的标准规定,ACK报文段可以携带数据。但如果不携带数据则不消耗序号,这种情况下,下一个数据报文段的序号仍是seq=x+1。这时,TCP连接已经建立,AB进入已建立连接(ESTABLISHED)状态。
为什么需要三次确认呢?
- 两次确认就不可以了呢?为什么需要三次确认呢?
- 现假设A第一次发送的连接请求报文因为网络问题长时间滞留了,到第二次通信完成释放连接后才到达B,这就是一个已失效的报文,但此时B以为是A的又一次连接请求,于是发出了确认,若没有第三次确认,连接就成功建立了。由于A现在并没有发出建立请求,所以B回复的确认A不理睬,所以不与B进行通信,然而B就一直等着A发数据给他,就这样,服务B就会一直等着浪费B的资源。
-
如果文章有帮助到你欢迎关注微信公众号《后端学长》