TCP三次握手、四次挥手?每次是哪端发送请求?为什么要四次挥手?三次不行吗?四次挥手中关键的是哪个?第四次挥手发送失败怎么办?重新发送的间隔时间是多久?
1,基础知识
TCP协议是一种面向连接、可靠的、基于字节流的传输层协议。面向连接是指在传输之前必须先建立连接,传输完成后要释放连接。
-
TCP端口号
TCP连接需要四个要素确定唯一连接:
(源IP,源端口号)+(目的IP、目的端口号)
在TCP首部预留了2个16位(两个字节)给端口号,而IP地址由上一层的IP协议负责传输。源端口号和目的端口号各占16位,即端口号的范围是0-65535,但1024以下是系统保留的,所以1024-65535是用户使用的端口范围。 -
TCP序号和确认号
<1>,序号seq:32位,TCP通信过程中某一端发送过来的字节流中每个字节的序号,通过这个来确认发送的数据有效,比如现在的序号位1000,发送了1000,下一个序号就是2000,可以理解为发送的具体信息。
<2>,确认号ack:32位,TCP对上一次序列号seq做出的确认号,用来响应TCP报文,接收端发出去的ack是它收到的seq+1。 -
TCP的标志位
<1>,SYN:synchronize,同步标志位,用于建立连接,同步序列号,SYN=1。
< 2>,ACK:acknowledge,确认标志位,对已接收到的数据包进行确认,ACK=1。
<3>,FIN:finish,完成标志位,表示我已没有数据要发送,即将关闭连接。 -
单工、半双工、双工
<1>单工:一方只能发消息,另一方只能接收消息,通信是单向的。类似于广播,只能通知,不能反馈。
<2>半双工:双方都能发消息,但同时只能有一方发。类似于对讲机,一方说完了话之后另一方才能说。
<3>双工:双方不仅都能发消息,还能同时发。类似于打电话,可以同时讲话吵架。
2,TCP三次握手
三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号seq和确认号ack(用确认号ack去同步序列号),交换TCP窗口大小信息。在socket编程时,客户端执行connect()函数时,将触发三次握手。
刚开始客户端处于closed状态,服务端处于Listen状态。
-
第一次握手
客户端将TCP报文同步标志位SYN设置为1,SYN=1(客户端请求建立连接)。随机产生一个序列值seq=J,保存在TCP首部序列号字段里,指明客户端需要连接的服务端端口号,然后将整个数据包发送出去,客户端进入SYN_SENT状态。 -
第二次握手
服务器收到数据包后由SYN=1知道客户端请求建立连接,于是服务端将自己要发送出去的报文的同步标志位SYN(服务端请求建立连接)和ACK(服务端告诉客户端我已经收到了你的消息)都置为1,ack=J+1,同时也随机产生一个序列号seq=K,然后服务端将数据包发送给客户端,服务端进入SYN_RCVD状态。 -
第三次握手
客户端收到报文后,检查ack是否为J+1,ACK是否为1,如果同时满足,则将要发从出去的报文的ACK置为1,ack=K+1,将该数据包发送给服务器端,客户端进入ESTABLISHED状态。
服务器端收到报文后,检查ACK是否为1,ack是否为K+1,如果是,服务端进入ESTABLISHED状态。此时完成三次握手,双方连接建立成功,客户端和服务端之间可以传输数据了。
3,为什么是三次握手而不是两次握手?
如果只有两次握手那将出现如下情况:
1,客户端发送第一次握手请求的时候,由于某种原因滞留了,客户端由于迟迟没有收到服务端发送的第二次握手确认请求,于是重新发送第一次握手请求,然后收到确认请求,连接成功,发送数据,关闭连接。
2,由于客户端第一次握手请求,延误到某个时间后到达了服务端,服务端以为客户端要申请连接,于是发送确认回复给客户端,两次握手,连接成功。但此时客户端想传的信息已经传完,客户端处于关闭状态,忽略服务端发来的确认,不向服务端发送任何数据,但服务端一直等待客户端的数据,浪费资源。
4,第三次握手失败怎么办?
服务器在第二次握手之后就会启动定时器,等待客户端的第三次握手确认。如果服务端超过规定时间没有收到客户端的第三次握手确认,就会启动重传机制,重新第二次握手,默认重传次数是5次。超过次数后服务端还没收收到客户端的第三次握手,服务端发送RST包(复位,强制关闭连接),进入CLOSED状态,关闭这个连接。
5,四次挥手
建立一个连接需要三次握手,而终止一个连接需要四次挥手,这是由TCP的半关闭造成的。TCP是全双工通信,每个方向必须要单独进行关闭,当端1没有数据要发送时端1关闭,端2接收不到数据,但端2仍能发送数据,所以端2也需要单独关闭。客户端和服务端都可发起挥手动作,由close()函数发起。
刚开始双方都处于ESTABLISHED状态,假设由客户端发起关闭请求:
-
第一次挥手
客户端没有数据要发送给服务端,向服务端发送FIN报文,表明请求断开连接,同时发送序列号seq=u,客户端进入FIN_WAIT1状态,等待终止。 -
第二次挥手
服务端收到客户端的请求,针对客户端的FIN进行应答ACK=1,ack=u+1,同时发送序列号seq=v,服务端进入CLOSE_WAIT状态,等待自身连接关闭。
客户端连接关闭,等待服务器连接关闭请求,客户端处于FIN_WAIT2状态,如果此时服务端仍有数据发过来,客户端仍然要接收。 -
第三次挥手
服务端发送关闭连接请求,FIN=1,ACK=1,ack=u+1,同时发送序列号seq=w,进入LAST_ACK状态,等待客户端确认。 -
第四次挥手
客户端同意服务端连接关闭,ACK=1,ack=w+1,同时设置序列号seq=u+1,进入TIME_WAIT状态,等待两个MSL时间后还没由收到任何来自服务端的消息后静进入CLOSED状态。
服务端一收到确认消息后就进入CLOSED状态。
6,为什么握手是三次,挥手是四次?
- 当建立连接的时候,在第二次握手,服务端向客户端同时发送ACK+SYN,其中ACK是用来响应客户端发起的第一次握手,SYN是用来同步的,因此只需要三次握手。
- 在断开连接的时候,当客户端发起第一次挥手之后,告诉服务端我已没有数据要发送,服务端收到FIN请求并发送ACK第二次挥手,告诉客户端我知道你没有数据要发送了,但此时服务端仍然可以继续发送数据,socket不会立刻关闭,只有等我服务端全部数据发送完毕之后再发送FIN请求,因此多了一次挥手,需要四次挥手。
7,四次挥手中最关键的是哪个?为什么?
第四次
原因:即使收到了对方的FIN报文,也需要等待两个MSL(报文段在网络中被允许存在的最长时间)才会彻底关闭这条连接。
<1>当第四次挥手失败,第四次ACK报文没有到达服务端,服务端没有收到客户端的ACK报文,于是重传,服务端重新发起第三次挥手FIN+ACK。失败的第四次挥手和重传的第三次挥手消耗的时间加起来就是2个MSL。
<2>经过两个MSL之后,网络中与该连接相关的包都消失了(即重发也失败),不会干扰新的连接。
8,TCP/IP协议包含几层?
- TCP/IP五层协议只是OSI和TCP/IP的综合,实际应用还是TCP/IP的四层结构。
- OSI:open system interconnect 开放系统互连。
- TCP/IP:transmission control protocol/ internet protocol 传输控制协议/网际协议。TCP/IP协议不仅仅指的是TCP 和IP两个协议,而是指一个由FTP、SMTP、TCP、UDP、IP等协议构成的协议簇, 只是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。
<1>应用层:为用户提供应用程序,该层的协议有DNS(Domain Name Syetem域名系统)、HTTP(HyperText Transfer Protocol 超文本传输协议)等。
<2>传输层:为应用程序间提供通信,该层的协议有TCP、UDP。
<3>网络层:负责数据包的路由和转发,该层的主要协议有IP协议。
<4>网络接口层:实现网卡接口的网路驱动程序,以处理数据在物理媒介上的传输,该层主要协议有ARP协议(Address Resolve Protocol 地址解析协议)、RARP协议(Reverse Address Resolve Protocol 逆地址解析协议)。
9,UDP协议是什么?UDP与TCP协议的区别?
UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送,没有超时重发机制,传输速度很快,不能保证是否到达目的端。
TCP和UDP都是传输层协议,区别在于:
-
面向报文:应用层交给UDP多大的报文,UDP就传输多大的报文。
-
面向字节流:当应用程序传输的数据太长,TCP可以把它划分后再依次传输;如果传输太短,也可以积累到一定量后再传输。
-
流量控制:发送方发送数据过快,接收方来不及处理。
解决方法:利用滑动窗口,接收方返回数据的时候会包含自己接收窗口的大小,以控制发送方的数据发送。 -
拥塞控制:过多的数据注入到网络中,路由器过载。
解决方法:只要网络中没有出现拥塞,拥塞窗口就大一些,以便把更多的数据发送出去;若干出现拥塞,就把拥塞窗口缩小一点,减少注入到网络中的分组。 -
粘包:TCP会出现的问题,接收方无法分辨消息与消息的边界在哪里。
解决方案:
① 发送定长包。每个消息的大小都是一样,接收方只要累计接收数据,只要数据等于一个定长的数值就将它视为一个消息。
② 设置分隔符。用特殊标记来区分消息间隔,这样可能导致如果消息内含有特殊标记的话,会被误判。
③ 包头加上包体长度。包头说明包体长度,接收方先接收包体长度,再按长度来接收消息。