一 TCP协议头部格式简述
前32个字节是源端口号和目的端口号;
Sequence Number:序列号指的是segment中第一个字节的编号,而不是segment的编号,建立TCP连接时,双方随机选择序列号;
Acknowledgement Number:确认号(可以理解为希望接收到的下一个字节的序列号);累计确认:该序列号之前的所有字节均已被正确接收到(比如我收到的确认号是13,则表示前12个字节都已收到);
Window Size: 接收端设置,用来表示还能接收多少个字节,用于TCP的流量控制;
ACK(Acknowledgment):取值为1表示Acknowledgement Number有效,这是一个确认包;取值为0,则表示这不是一个确认包;
SYN(Synchronize):取值为1,表示这是一个建立TCP连接的包,其中三次握手的前两次就设置SYN为1,其它不设置;
FIN(Finish):表示要结束一个TCP会话。
二 三次握手
第一次:将SYN置为1(表示请求建立连接,此时ACK为0),随机生成一个序列号x赋给seq,发送给服务端;
第二次:服务器收到并进行确认,将SYN和ACK都置为1(ACK置为1表示这是一个确认包),随机生成一个序列号y赋给seq,并置确认号ack为x+1;
第三次:客户端收到并进行确认,将ACK置为1(此时SYN为0),序列号为x+1(就是服务器的确认号),并置确认号ack为y+1。
三 四次挥手
第一次:客户端向服务器发送FIN,用于关闭client向server的数据发送,客户端进入FIN_WAIT_1状态。
第二次:Server端收到FIN,向Client发送ACK(确认号ack为收到的序列号加1),Server端进入CLOSE_WAIT状态(客户端收到ACK后会进入FIN_WAIT_2状态);
第三次:Server向Client发送FIN,Server进入LAST_ACK状态;
第四次:Client收到FIN,客户端进入TIME_WAIT状态,接着向Server发送ACK(确认号ack为收到的序列号加1),服务器端收到ACK后会进入CLOSED状态。Client等待2个MSL后进入CLOSED状态。
四 总结
1.为什么是三次握手,而不是两次?
答:三次握手是为了防止已失效的连接请求报文段再次到达而建立连接,导致资源浪费。
失效的连接请求报文段的产生:当客户端发送连接请求时,由于长时间没有得到回应而再次发送建立连接的请求,这次连接成功建立;然而第一次的请求并没有丢失,只是延误到达,这就又建立了一个连接;但客户端并不清楚,所以对于这个连接既不发送数据,也不关闭连接,进而导致资源浪费。
2.为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
答:因为服务器端在LISTEN状态下收到建立连接的请求后,将SYN和ACK一起发送给了客户端。
而当客户端发送请求关闭连接时,服务器端或许还有数据要传输,因此需要等待一会才能关闭连接,这是不能讲FIN和ACK一起发送。
3.为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:如果客户端发送的ACK,服务器端没有收到,服务器端会再次发送FIN,这是客户端还可以再次进行确认。