TCP为什么要三次握手?为什么不能两次握手或四次握手?
- 三次握手是确认客户端和服务端的发送和接受报文的能力是否正常。
- 如果是两次握手,服务端受到客户端的历史SYN报文就建立连接,会空耗服务端资源。
- 确认双方发送数据的初始序号,因为都要给对方发送确认报文,表达已知悉。
三次握手是确认客户端和服务端的发送和接受报文的能力是否正常。三次握手足够判断这一点了,四次握手其实多余了,没有必要浪费时间去发送没有意义的报文。
如果不加确认,进行两次握手,服务端收到客户端的SYN报文就直接建立连接,有可能客户端的SYN报文发生了网络拥堵,客户端进行了超时重传,随后拥堵的报文又成功传到了服务端,服务端判断不了这是新的连接请求报文还是历史连接报文,如果服务端收到SYN报文直接建立连接,接受到了客户端历史的SYN报文,会发生空等待,消耗服务端的资源。
TCP三次握手过程
- 客户端发送SYN报文,告知对方初始序号,是否会告知窗口大小
- 服务端收到后,回应SYN+ACK报文,告知对方初始序号
- 客户端收到后,回应ACK报文,客户端建立连接,服务端收到ACK后建立连接
RFC 793 - Transmission Control Protocol 其实就指出了 TCP 连接使用三次握手的首要原因 —— 为了阻止历史的重复连接初始化造成的混乱问题,防止使用 TCP 协议通信的双方建立了错误的连接。
The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.
如果是两次握手,正常流程就是,客户端发送SYN,服务端接收到SYN开始建立连接,并发送ACK给客户端,客户端收到ACK开始建立连接。
客户端发送SYN后,可能发生拥堵,然后客户端超时重传SYN,接下来按照正常流程建立连接,然后过了一会服务端又收到了之前拥堵发过来的SYN,并不能确定它历史的连接还是新的连接,如果此时建立新连接就会一直等待客户端发送数据,而这只是一条历史的连接报文,客户端不会发送数据,服务端就会空等,浪费了资源。
如果是三次握手,服务端接收到SYN后,会发送SYN+ACK给客户端,由客户端来判断是否是历史连接,如果序号过期,则认为是历史连接,向服务端发送RST取消连接的建立。服务端是没办法判断客户端的序号是否过期。
TCP 建立连接时通过三次握手可以有效地避免历史错误连接的建立,减少通信双方不必要的资源消耗,三次握手能够帮助通信双方获取初始化序列号,它们能够保证数据包传输的不重不丢,还能保证它们的传输顺序,不会因为网络传输的问题发生混乱,到这里不使用『两次握手』和『四次握手』的原因已经非常清楚了:
- 『两次握手』:无法避免历史错误连接的初始化,浪费接收方的资源;
- 『四次握手』:TCP 协议的设计可以让我们同时传递 ACK 和 SYN 两个控制信息,减少了通信次数,所以不需要使用更多的通信次数传输相同的信息;
TCP三次握手中,服务端发送了SYN+ACK后,一直没有收到客户端的ACK会怎样?
server端如果在一定时间内没有收到的TCP会重发SYN-ACK。在Linux下,默认重试次数为5次,重试的间隔时间从1s开始每次都翻售,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s,总共31s,第5次发出后还要等32s都知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63s,TCP才会把断开这个连接。
TCP为什么要先建立连接才能传输数据?
因为如果不确定对方能够正常的接受和发送数据,一方单方面发送数据就是无意义的资源浪费。
TCP建立连接时做了什么事?
- 确认双方的发送能力、接受能力是否正常
- 确定双方发送报文的初始编号
- 确定窗口大小
- 确定MSS-最大传输包大小
- 确定是否使用SACK
TCP什么时候可以传输数据?
第三次握手客户端就可以携带数据了,因为受到服务端的SYN+ACK报文,确认了服务端的接受能力和发送能力是正常的
TCP建立连接时的SYN指令是做什么的?
同步SYN:连接建立时用于同步序号。当SYN=1,ACK=0时表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文。SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0。
什么是SYN攻击?
客户端发送SYN报文后,服务端会进入SYN_RCVD状态,但服务端发送出去的SYN+ACK报文没有应答,SYN报文发送多了后,会占满服务端的半连接队列
RST消息是什么时候发送?
建立连接出现错误就会发送RST报文关闭连接
1、端口未打开
2、请求超时
3、提前关闭
4、在一个已关闭的socket上收到数据
5、用于拒绝一个非法连接