你需要知道的TCP/IP( 四 )


你需要知道的TCP/IP

文章插图
 
源端口号(Source Port)占用 2 个字节 。标识 发送端 程序的端口号,当接收端需要回复消息的时候,需要带上这个端口号 。
目的端口号(Destination Port)占用 2 个字节 。标识 接收端 程序的端口号,可以传递给监听在这个端口的程序
控制位(Control Flag)占用 6 位,不满一个字节 。标识当前 TCP 包是什么包,在通信过程中有一些特殊作用 。
SYN表示希望建立三次握手链接,并初始化序列号 。
ACK对收到数据包的应答确认 。接收端接受数据之后,会回复 ACK 包,发送端从其上 确认应答号 知道接收端哪些数据已经接受了 。
FIN表示没有数据发送了,希望断开连接
PASH接收端接收到这个数据包需要立刻传递给应用层,不能等待接收更多的数据包
RET链接出现异常,需要强制断开连接
URG表示包中有需要紧急处理的数据
序列号(Sequence Number)占用 4 个字节 。TCP 三次握手的时候,发送端和接收端各自初始化(随机的)自己的 `序列号 。
我们可以这样理解,发送端发送的数据就是一个字节数组,这个数组中每个字节都有一个 序列号 。
发送端和接收端都有自己的序列号,并且不相同,在三次握手的时候自己初始化,然后告知对方 。
确认应答号(Acknowledgement Number)占用 4 个字节 。确认应答号 也是指的序列号,指的是期望发送端下次发送的序列号,这个序列号(确认应答号)之前的数据已经接受处理了 。
下图是我抓包建立三次链接,然后我发送三次 1n 数据 。
三次握手,发送端通过发送 SYN 包,发送自己的初始化序列号(893189542),然后发送的每个字节都会有一个序列号 。
接收端发送 ACK 包中的 确认应答号,指明这个序列号之前的数据我已经接受了 。
你需要知道的TCP/IP

文章插图
 
窗口大小(Window Size)窗口大小适用于流控的 。发送端不能一直发送消息,需要根据接收端的接受能力来调整发包的速率 。
你需要知道的TCP/IP

文章插图
 
内核会为每个 TCP/IP 分配读写缓冲区,网卡会从写缓冲区中把数据取走,然后发送 。
TCP/IP 是可靠连接,所以它需要记录哪些数据发送已被对方接受了(由确认应答号可以知道),接受的数据会被淘汰掉,节省内存空间 。
窗口大小作用:接收端会通过 ACK 告诉发送端调整窗口大小 。
当窗口中的数据全都是已发送未确认数据时,发送端不能再发送新的数据,必须等待窗口空出位置来 。
你需要知道的TCP/IP

文章插图
 
当有一个数据包被确认了,发送端就可以发送新的数据包 。已发送未确认数据会在超时的时候重新发包 。
校验和 (Checksum)占用 2 个字节 。校验和 用于校验数据包是否损坏 。每个数据包都一个校验和,接收端接收到数据之后,使用相同的算法对数据计算出一个 hash值,然后跟数据包的校验和比较,不一样说明数据在传输过程中损坏了,接收端会丢弃这个包,等待发送端重新发这个包 。
TCP 中 MSS链路层能发送的最大以太网帧为 1500 字节,MTU 为 1500 。
IP 数据包能发送的最大数据 = MTU - IP 首部大小(一般 20 字节),IP 数据包超过这个 1500 字节会分片
TCP 传输数据以段 (Segment) 为单位 。
TCP 为了避免分片,会主动将数据分片之后交给网络层 。TCP 能传输的最大分段(只是数据不包括首部)称之为 Max Segment Size,简称为 MSS 。
MSS = MTU - IP 首部大小 - TCP 首部大小
在以太网中 TCP 的 MSS = 1500(MTU) - 20(一般 IP 首部大小) - 20(一般 TCP 首部大小)= 1460,这个值需要根据首部计算
你需要知道的TCP/IP

文章插图
 
MSS 值在三次握手时,会通过 MTU 计算的 。
TCP 三次握手建立连接
你需要知道的TCP/IP

文章插图
 
图片来自 码出高效:Java 开发手册
为什么是三次握手建立连接呢?很多面试官也会问 。这其实是可靠连接的最少握手次数 。
你需要知道的TCP/IP

文章插图
 
图片来自 码出高效:Java 开发手册


推荐阅读