TCP
传输控制协议(Transmission Control Protocol,TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP协议位于四层模型中的传输层
TCP报文
源端口:16bit,共65536个端口,端口0有特殊含义,不能使用,这样可用端口最多只有65535。
目的端口:16bit,接收方的端口号。
序号:32bit,可靠传输服务的关键字段。序号(sequence number, seq)是报文段首字节的字节流编号,TCP把数据看成是有序的字节流,TCP会隐式地对数据流的每个字节进行编号。第一个包的编号由本地随机产生,到达2^32-1后会再回到0。客户端、服务器端有各自的seq序号。序号主要用来解决网络包乱序(reordering)问题。
确认号:32bit,可靠传输服务的关键字段。确认号(acknowledgment number,ack)是期望的对方的下一个序号。主要用来解决不丢包的问题。
首部长度:4bit,以32bits4字节为单位,这样首部最大长度为15 * 4 = 60字节。除去固定部分的长度20字节,可变部分的长度最大为40字节。首部长度也称数据偏移,由于报头的长度可变 ,首部长度指示了数据区在报文段中的起始偏移值 。
保留:6bits。
标志:6bits。URG、ACK、PSH、RST、SYN、FIN共6个,每一个控制位表示一个控制功能。(这里需要注意的是不要把这里的标志位SYN,ACK和上面的序号seq和确认号ack相混淆,这两个是不同的东西)
URG:紧急指针标志,为1时表示紧急指针有效,为0则忽略紧急指针。
ACK:确认号标志,为1时确认号有效 ,为0时确认号无效。TCP 规定除了最初建立连接时的 SYN 包之外该位必须设置为 1 。
PSH:推送标志,为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。
RST:重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求。
SYN:同步序号标志,用于建立连接,在连接建立时同步序号,SYN=1时表示这是一个连接请求或连接接受报文
当SYN=1且ACK=0时,表明这是一个连接请求报文段
当SYN=1且ACK=1时,表明对方同意建立连接
SYN=1的报文不能携带数据,但要消耗掉一个序号。SYN=0、ACK=1的报文可以携带数据,如果不携带数据则不消耗序号,此时下一个报文的序号与当前报文的序号相同(注意理解这里)。
FIN:终止标志,用于释放连接,值为1表示要发送的数据报已经发送完毕,需要释放传输连接。
窗口:16bit,单位字节。滑动窗口大小,用于接收端告知发送端,本接受端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口最大为2^16-1=65535字节。这也限制了TCP的吞吐量,可以通过窗口缩放选项对这个值进行缩放。
校验和:奇偶校验,此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字节进行计算所得。由发送端计算和存储,并由接收端进行验证。
紧急指针:只有在URG字段打开时才有效。暂时不清楚有啥用
选项:长度可变,最长40字节,当没有选项时报头长度是20字节。常见的有MSS,window scale,时间戳,SACK。
填充:选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍。
数据部分: TCP 报文段中的数据部分是可选的。
在一个连接建立和终止时,双方交换的报文段仅有 TCP 报头。如果一方没有数据要发送,也使用没有任何数据的报头来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报头。
ACK标志为1的TCP报文能否携带数据?
ACK标志为1的TCP报文,表示报文中的确认号有效,TCP 规定除了最初建立连接时的 SYN 包之外该位必须设置为 1 。可以携带数据也可以不携带数据,如果不携带数据则不消耗序号。ACK只是TCP的一种确认机制,接收端接收到数据后不需要马上回复一条ACK报文,接收端可以延迟确认,也可以跟随将要发送的数据一起过去这时ACK虽然为1但是却携带了数据,避免传输只有TCP头的空报文。
参考
理解TCP序列号(Sequence Number)和确认号(Acknowledgment Number) 译文,通过抓包来解释seq number和ack number。
Understanding TCP Sequence and Acknowledgment Numbers 原文
就是要你懂 TCP 阿里中间件团队博客