面试经典问题 — TCP 详解
TCP 数据包结构
源端口号:表示发送端端口号,字段长为16位。
目标端口号:表示接收端口号,字段长为16位。
序列号(seq):为当前端成功发送的数据位数(由计算机生成的一个随机数作为其初始值,以后再将每次成功转发过去的字节数累加到初始值上表示数据的位置 )。
确认号:为当前端成功接收的数据位数+1。(表示下一次应该收到的数据位置,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收)
首部长度:该字段长度为4位,单位为4字节(32位)。TCP首部长度不包括选项的话,是20个字节,20/4=5,5的二进制序列:0101,报头长度也叫数据偏移,所以该字段可以设置为5,选项字段最大的是40字节,所以,TCP首部长度为最大为20+40=60字节,该字段可以设置的最大长度为60/4=15。
保留位:该字段主要是为了以后扩展时使用,其长度为6位。一般设置为0,即使收到的包在该字段不为0,此包也不会丢弃。
标志位:字段长为6,每一位从左到右分别为:URG、ACK、PSH、RST、SYN、FIN。当对应的值为1,表示有具体含义:
URG:紧急指针是否有效。为1,表示某一位需要被优先处理。
ACK:确认号是否有效,一般置为1。
PSH:提示接收端应用程序立即从TCP缓冲区把数据读走。
RST :对方要求重新建立连接,复位。
SYN:为1表示请求建立连接,并在其序列号的字段进行序列号的初始值设定。
FIN:希望断开连接。
窗口大小:接收缓冲区的大小,TCP不允许发送超过此处所示大小的数据。
校验和:发送端填充,CRC校验,接收校验不通过,则认为数据有问题。和UDP的区别是,UDP校验的是数据本身,TCP校验的不仅包含TCP首部,而且包含TCP数据部分。
紧急指针:只有在URG为1时有效,该字段为1表示本报文的段中的紧急数据的指针。
选项:用于提高TCP的传输性能。需要根据首部长度进行控制,其最大长度为40字节。
数据:真实有效数据
那么问题又来了:
1.为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。
2.为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能不会马上关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
TCP的优点:
可靠,稳定 。TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。
TCP的缺点:
慢,效率低,占用系统资源高,易被攻击, TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU、内存等硬件资源。