运输层
概述
- 之前课程所介绍的计算机网络体系结构中的物理层、数据链路层以及网络层它们共同解决了将主机通过异构网络互联起来所面临的问题,实现了主机到主机的通信。
- 但实际上在计算机网络中进行通信的真正实体是位于通信两端主机中的进程。
- 如何为运行在不同主机上的应用进程提供直接的通信服务是运输层的任务,运输层协议又称为端到端协议。
- 运输层向高层用户屏蔽了下面网络核心的细节(如网络拓扑、所采用的路由选择协议等),它使应用进程看见的就好像是在两个运输层实体之间有一条端到端的逻辑通信信道。
根据应用需求的不同,因特网的运输层为应用层提供了两种不同的运输协议,即面向连接的TCP和无连接的UDP,这两种协议就是本章要讨论的主要内容。
运输层端口号、复用、分用概念
端口号
- 运行在计算机上的进程使用进程标识符PID来标志。
- 因特网上的计算机并不是使用统一的操作系统,不同的操作系统(windows,Linux,Mac oS)又使用不同格式的进程标识符。
- 为了使运行不同操作系统的计算机的应用进程之间能够进行网络通信,就必须使用统一的方法对TCP/IP体系的应用进程进行标识。
- TCP/IP体系的运输层使用端口号来区分应用层的不同应用进程。端口号使用16比特表示,取值范围0~65535;
- 熟知端口号:0~1023,IANA把这些端口号指派给了TCP/IP体系中最重要的一些应用协议,例如:FTP使用21/20,HTTP使用80,DNS使用53。
- 登记端口号:1024~49151,为没有熟知端口号的应用程序使用。使用这类端口号必须在IANA按照规定的手续登记,以防止重复。例如:Microsoft RDP微软远程桌面使用的端口是3389。
- 短暂端口号:49152~65535,留给客户进程选择暂时使用。当服务器进程收到客户进程的报文时,就知道了客户进程所使用的动态端口号。通信结束后,这个端口号可供其他客户进程以后使用。
- 端口号只具有本地意义,即端口号只是为了标识本计算机应用层中的各进程,在因特网中,不同计算机中的相同端口号是没有联系的。
发送方的复用和接收方的分用
在发送方中,多个进程通过端口利用一个运输层协议将数据封装成报文后发送,这就称为发送方复用,不同协议就叫不同协议复用,如图中的UDP复用。
在IP复用中也会根据协议字段的不同将其使用不同协议再次进行封装。
在接收方中,利用一个协议,将用报文解析成不同数据,将数据根据端口发送不同进程,这就称为接收方分用。
在IP分用中也会根据协议字段的不同将其使用不同协议进行解析。
在TCP/IP体系的应用层常用协议的运输层熟知端口号:
举例
针对上述知识,我们对一个域名访问中的运输层传输流程进行解读:
首先先认识在一次运输层传输中的主要路由器:
DNS服务器:记录有某域名所对应的IP地址,在输入网页域名后,在hosts中找不到网页对应的IP地址时,就要通过DNS服务器获取域名对应的IP地址。
Web服务器:某域名的服务器,也就是前面几章所说的目的主机,在访问域名时IP数据报最终即使到达Web服务器,服务器进行响应。
输入域名
如果hosts文件中有域名对应的IP,直接发送带有目的地址的IP数据报。
若计算机中没有该域名对应的IP地址,进行以下操作:
- 构建DNS请求报文:
在本机的空闲的短暂端口中选择一个暂时的端口,并发送IP数据报到DNS,对应DNS的53号端口。
- 将该UDP请求数据报通过以太网发送给DNF服务器。
- DNS服务器端进程解析DNS查询请求报文的内容,然后按照其要求查找对应的IP地址。查找到后会发送DNS响应报文。
- 接收方将UDP用户响应数据报封装在IP数据报中发送给发送方。
- 解析DNS发送的响应报文,在向解析出来的 192.168.0.3 IP地址发送TCP请求。发送时和UDP一样,在本地需要80默认端口来对应http请求.
- Web服务器收到请求后,就发送响应报文,封装页面信息。
- 用户收到后,在浏览器渲染展示页面。
UDP和TCP的对比
- 用户数据报协议UDP(User Datagram Protocol)、传输控制协议TCP(Transmission Control Protocol)
- UDP和TCP是TCP/IP体系结构运输层中的两个重要协议,其使用频率仅次于网际层的IP协议
- 运输层采用面向连接的 TCP 协议时,尽管下面的网络是不可靠的(只提供尽最大努力服务),但TCP协议就相当于在逻辑上建立了一条通信信道,该信道是全双工的可靠信道。
- 当运输层采用无连接的 UDP 协议时,这种逻辑通信信道是一条不可靠信道。
链接方式
UDP是无连接的通信方式
TCP是通过著名的“三次握手”建立连接,“四次挥手”释放连接。
传播方式
发送报文方式
UDP协议中,对于应用层传输下来的报文不进行处理,保留报文的边界。在给报文加上UDP首部,进行发送。UDP接收方首部接收到UDP数据后,去除其首部,交付给应用层。
可以看出,UDP是针对报文为单位进行处理的,也就是UDP是面向应用报文的。
在TCP协议中比较复杂:
在TCP发送方:TCP协议会把应用进程交付下来的数据块(报文)看作是一连串无结构的字节流(TCP并不知道这些子节含义),将他们编号,并存储在自己的发送缓存中,TCP再根据发送策略,提取一定量的字节,加上TCP首部,构建成TCP报文进行发送。
对于接收方,同时进行两件事:
从所接受到的TCP报文段中,取出数据载荷部分并存储在接收缓存中,同时将接收缓存中的一些字节交付给应用进程。有两个点值得注意:
- TCP协议保证接收方收到的字节流和发送方应用进程发出的字节流完全一样
TCP不保证接收方应用进程所收到的数据块与发送方发送的数据块,具有对应大小的关系,例如,发送方应用进程交给发送方的TCP共10个数据块,但接收方的TCP可能只用了4个数据块,就把收到的字节流交付给了上层的应用进程。但。就是不会全部将数据交付给上层。- 因此接收方的TCP应用进程必须有能力识别收到的字节流,把它还原成有意义的应用层数据
可以看出,TCP对报文的处理是以子节为单位的,也就是TCP是面向字节流的,这正是TCP实现可靠传输、流量控制、以及拥塞控制的基础
报文段
由于UDP不提供可靠传输的服务,因此其首部只需要在网际层的基础上添加区分端口的子节,其首部比较简单。
在TCP中,需要提供可靠传输、流量控制、拥塞控制等服务,首部比较复杂,字段比较多。
可靠性
UDP提供的是不可靠服务:
对于发送的UDP数据报,接收方在检测到其误码后直接丢弃,不做其他操作。对于发送方发送过程中出现分组丢失,也不做处理。因此其传输数据是不一定能使接收方全部收到数据,因此是不可靠服务。TCP提供的是可靠服务:
由于TCP字传输过程中需要建立连接,通过建立的可靠信道进行传输,因此不会出现传输差错,也就是误码、丢失、乱序、重复。因此可以保证发送端发送什么,接收端接收到什么,是可靠传输。
总结
TCP的流量控制
概述
- 对于数据传输中,我们希望传输的越快越好,但是若传输过快会导致接收方不够时间接收数据,造成数据丢失。
- 流量控制就是为了让发送方速率不要太快,要让接收方来的及接收。
- 利用滑动窗口机制可以很方便的在TCP连接数实现对发送方的流量控制。
举例
设定滑动窗口为400,A向B传输了2段数据,均未发生错误
响应报文含义:
- ACK = 1:这是一个TCP确认字段
- ack = 201 :201编号以前的数据全部确认收到
- rwnd = 300 : 将接收窗口大小调整为300
第一次流程控制:如果在201300字节发生错误,对面前收到的1201数据进行累计确认,并调整窗口为300字节,并移动窗口到确认的地方(注意:如果只确认了1101,那么就窗口就只能移动到101200那里),A就在缓存中清除已经确认了的报文段。
在发送滑动窗口大小的数据
第二次流程控制:此时由于201-300分组丢失超过重传计数器设置时间,对开始重传201-300分组。接收方在收到501号所有分组后,发送新的ACK确认报文,报文中将窗口设置为100大小。
第三次流程控制:在接收方接收到ACK报文后,对前500子节数据在缓存中删除,并将窗口调整为100,然后调整滑动窗口位置,开始新的传输。传输窗口数据后不再传输数据。等待ACK确认信号。此时接收方接收到数据后再次发送ACK报文,将窗口大小设置为0。
此时窗口为0,不再发送数据。
但此时会出现问题:
- 在缓存不足,接收方窗口调整为0后,过了一段时间便有了新的空间,此时发送一个新的调整窗口报文,但是此时报文传输丢失!无法到达发送方。
- 此时就会出现发送方等待接收方有缓存空间,接收方等待发送方发送数据的死锁情况。
为了解决这个问题,TCP为每一个连接设有一个持续计时器
在连接的一方接收到对方的零窗口通知后一段时间后,超时计时器到时,就会发送一个1子节的零窗口发送报文,在接收方接收到该信号后,就会通告自己的窗口大小。当知道窗口可以传输数据后,就会开始通信。
- 上图如果零窗口探测报文在发送过程中如果丢失,还是能打破死锁局面
- 因为零窗口探测报文段也有重传计时器,重传计时器超时后,零窗口探测报文段会被重传
TCP中规定不论接收方有没有空间,都必须接收发送方的3种报文:零窗口检测报文段、确认报文段、携带有紧急数据的报文段。
练习
解析
移动窗口
注意:题目描述是确认了第一个段,所以滑动窗口移动的地方不是2000,而是1000,因为1000~1999还没收到确认。
TCP拥塞控制
概述
- 拥塞指的是某段时间内,若对网络中的某一资源的需求超过了该资源所能提供的可用部分,网络性能就要变坏。
- 在计算机网络种的资源包括链路容量(带宽)、交换节点种的缓存和处理机等。
- 若出现拥塞而不进行控制,整个网络的吞吐量将随输入负荷的增大而下降。
- 可以将拥塞形象的理解为堵车
在图中,绿色指的是理想情况下不发生拥塞的情况,此时吞吐量与输入负载相等。当网络资源数被全部利用时,吞吐量不再增长。
红色线指的是出现拥塞不进行处理,会导致吞吐量下降,知道吞吐量为零,产生死锁现象。
蓝色线是实际的拥塞控制,在出现拥塞后采用拥塞控制措施,使吞吐量保持在一定水平。
接下来我们学习拥塞控制的4种算法:
为了介绍四种拥塞控制算法的基本原理,假定以下条件:
先了解拥塞算法中的基本思路:
- 发送方维护一个叫做拥塞窗口cwnd的状态变量,其值取决于网络的拥塞程度,并且**动态表换
- 拥塞窗口的维护原则:只要没有网络出现拥塞,拥塞窗口就再增大一些,只要网络出现拥塞,拥塞窗口就减少一些。
- 判断网络拥塞的依据:没有按时收到应到达的确认报文(发生超时重传)
- 发送方将拥塞窗口作为发送窗口swnd,即:swnd = cwnd
- 维护一个慢开始门限ssthresh状态便变量,其维护原则为:
慢开始算法
- 慢开始算法是用来确定网络的负载能力或拥塞程度。
- 算法是实现是由小到大逐渐增大(以倍数增长)拥塞窗口数值。
以一次数据报文传输过程学习慢开始算法:
- 慢开始指的是一开始网络注入的报文段少,并不是指拥塞窗口cwnd的增长速度慢。
- 开始的满开始门限值是16
- 接收方接收后,确认了报文段0,此时发送方的拥塞窗口门限值为上一次的2倍
- 对1~2段确认后,cwmd也变为上次的2倍
- 依次发送,第四次发送之后,拥塞窗口变为16,达到慢开始的门限值
此时慢开始算法结束。
拥塞避免算法
在达到慢开始的门限值后,使用拥塞避免算法。
- 拥塞避免算法让拥塞窗口 cwnd 缓慢地增大(每伦窗口大小+1),避免出现拥塞。
- 在拥塞避免阶段,具有 “加法增大” (Additive Increase) 的特点
- 拥塞避免算法并不能完全避免拥塞,只是在拥塞避免阶段将容易拥护的窗口控制为按线性规律增长,是网络比较不容易出现拥塞
接上面的例子:
- 此时cwmd窗口只加一,来进行传输
- 确认后再次加一进行传输
- 当出现报文丢失
- 此时如果重传计时器超时,那么很可能出现网络拥塞,将慢开始门限值减少为当时cwnd的一半,并将cwnd减少为1,重新开始慢开始算法的发送
- 重新开始慢开始算法发送
- 最终实际的发送情况
快重传
拥塞避免算法在传输过程中判断拥塞情况的缺点
所以出现了快重传算法。
- 快重传指的是在出现分组错误后,发送方尽快重传数据,而不是等待超时计时器超时再重传。
- 快重传算法三个原则:
- 要求接收方不要等等自己发送数据时才进行捎带确认,而是要立即发送确认。
- 即使收到了失序的报文段也要立即发出对已收到的报文段的重复确认
- 发送方一旦收到了3个连续的重复确认,就立即将相应的报文段立即重传,不用等到超时计时器超时后再重传。
- 对于个别丢失的报文段,发送方不会出现超时重传,也就不会误认为出现了拥塞(这会使拥塞窗口设置为1),该算法可以使整个网络吞吐量提高约20%。
举例:
- 在快重传算法中,发送方会在接收到确认分组前就发送下一个分组(前提是在拥塞窗口大小内),对于丢失的分组,会在收到3个分组后发送3个重复确认丢失分组序号。
- 接收方收到3个重复分组序号后便开始重传,而不是等待超时计时器到时。
- 这样子也不会误以为出现了拥塞。
快恢复
- 发送方在收到3个重复确认后,就知道现在只是丢失了个别的报文段。于是不开始启动慢开始算法,转而执行快恢复算法。
- 快恢复算法是发送方将慢开始门限ssthresh值和拥塞窗口cwnd值调整为当前窗口的一半,并开始直星拥塞避免算法。
- 有部分快恢复实现是把快回复开始时的拥塞窗口swnd值再增大一些,即等于SSTHRESH + 3,理由如下:
- 既然发送方收到3个重复的确认,就表明有3个数据报文段已经离开了网络;
- 这3个报文段不再消耗网络资源而是停留在接收方的接收缓存中;
- 可见现在网络中不是堆积了报文段而是减少了3个报文段。因此可以适当把拥塞窗口扩大些。
四个算法的结合情况
四个算法再传输过程中的使用顺序图:
练习
TCP超时重传时间的选择
概述
TCP超时重传时间的选择是TCP最复杂的问题之一。
往返时间RTTO大于超时重传时间的问题
超时重传时间RTO大于往返时间RTTO的问题
超时重传时间的选择
- 因此不能直接用某次测量得到的RTT样本值来计算超时重传时间RTO
- 要利用每次的量得到的RTT样本,计算加权平均往返时间RTTs(又称为平滑的往返时间)
- 用这种方法得出的加权平均往返时间RTTs就比测量出的RTT值更加平滑
- 显然,超时重传时间RTO应略大于加权平均往返时间RTTs
在RFC6298建议使用下式计算超时重传时间RTO:
往返时间测量的复杂
Karn算法:
因此,要对Karn算法进行修正。方法是:报文段每重传一次,就把超时重传时间RTO增大一些。典型的做法是将新RTO的值取为旧RTO值的2倍。
举例
在第三四此传播之后计算出TRO,在第五次出现重传时,此时就是用Karn算法的修正方法,将新RTO的值取为旧RTO值的2倍。
TCP可靠传输的实现
概述
- TCP基于以子节为单位的滑动窗口来实现可靠传输
在要传递的字节流中,可以大致分为几个区域:
- 发送窗口后数据(图中的左边):这些数据已经成功发送出去并且已经收到确认信号,因此这部分数据可以从缓存中删除
- 发送窗口中数据(图中的蓝色部分):这部分数据正处于发送窗口中,此时数据有两种情况,已发送正在等待确认或者未发送出去,对于已发送的数据要存在发送缓存中。
- 发送窗口前数据(图中的右半部分):这部分数据不允许发送。
如何描述窗口的状态?
过程描述
- 发送报文
- 当发送32~33时,接收方并没有接收到,所以返回确认报文段中,ack是31
- 发送方收到ack = 31报文后,知道31号数据未按序到达,但是根据上面所学的知识,只有第3次接收到同一个ack信号才会进行重传,此时不做处理,继续发送往下的数据。
- 此时若成功接收到31号数据,此时31-33号数据按序到达,此时接收方会择机将数据交给应用层,并且将窗口向后滑动3字节,同时发送确认报文。
- 此时若成功接收到31号数据,此时31-33号数据按序到达,此时接收方会择机将数据交给应用层,并且将窗口向后滑动3字节,同时发送确认报文。
- 确认报文发送时,还会一直发送数据
- 发送方收到确认报文后,将窗口移动到34,并将发送出去并收到的数据从缓存中清除
- 若发送方发送完全部的发送窗口数据,此时不能再发送数据。此时若迟迟等不到接收方确认信号,重传计时器超时,此时会重新发送发送窗口内已发送的数据,并重启重传计时器。
注意
练习
练习一
练习二
总结
TCP连接的建立
概述
- TCP是面向连接的协议,它基于运输连接来传送TCP报文段
- TCP运输连接的建立和释放时每一次面向连接的通信中必不可少的过程
- TCP运输连接建立有以下三个阶段:
- TCP的运输连接管理就是使运输连接的建立和释放都能正常地进行。
TCP连接所需要解决的问题
- 使TCP双方能够确知对方的存在;
- 使TCP双方能够协商一些参数(如最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量等);
- 使TCP双方能够对运输实体资源(如缓存大小、连接表中的项目等)进行分配。
三报文挥手建立连接过程
- 在三报文握手过程中,有两个角色,客户端发送握手连接请求,服务器等待接收请求。在最开始:双方都是处于关闭状态,此时双方的TCP进程都是关闭的。此时,TCP服务器在连接之前要进行准备。
准备过程中,服务器创建传输控制块,在块中有TCP连接表等一些TCP连接的重要信息。创建后便开始监听,准备接收来自客户端的连接请求。
- 准备好之后开始第一次握手
在打算建立TCP连接时,客户端向TCP服务器进程发送TCP连接请求报文段,并进入同步已发送状态
TCP连接请求报文段首部中,有两个关键数据:
- 同步位SYN:被设置为1,表明这是一个TCP连接请求报文段
- 序号字段seq:被设置了一个初始值x,作为TCP客户端进程所选择的初始序号
- 服务器接收到连接请求后,开始第二次握手,发送确认报文
TCP服务器进程收到客户端发送的TCP连接请求报文段后,如果同意建立连接,则向TCP客户进程发送TCP连接请求确认报文段,并进入同步已接收状态
TCP连接请求确认报文段首部中有几个关键数据位:
- 同步位SYN和确认为ACK:都设置为1,表明这是一个TCP连接请求确认报文段。
- 序号字段seq:设置了一个初始值y,作为TCP服务器进程所选择的初始序号。(TCP服务器随机生成的)
- 确认号字段ack:值被设置成了x+1,这是对TCP客户进程所选择的初始序号(seq)的确认。
- 值得注意的是:这个报文段也不能携带数据,因为它是SYN被设置为1的报文段,但同样要消耗掉一个序号
- 发送方接收到确认报文后,开始第三次握手:
TCP客户进程收到TCP连接请求确认报文段后,还要向TCP服务器进程发送一个普通的TCP确认报文段,并进入连接已连接状态
普通的TCP确认报文段首部中有以下重点数据位:
- 确认位ACK:设置为1,由于没有SYN同步字段,表明这是一个普通的TCP确认报文段,表示已确认收到建立连接报文。
- 序号字段seq:设置为x+1,因为TCP客户进程发送的第一个TCP报文段的序号为x,所以TCP客户进程发送的第二个报文段的序号为x+1(SYN字段报文需要消耗一个序号)
- 确认号字段ack:设置为y+1,这是对TCP服务器进程所选择的初始序号的确认
值得注意的是:TCP规定普通的TCP确认报文段(只有ACK没有SYN)可以携带数据,但如果不携带数据,则不消耗序号
三报文握手可以修改为二报文握手吗?
不能
举例
TCP发送了一条连接请求,但是由于某种原因造成了较长时间的迟到现象,导致TCP服务器没有接收到,TCP客户端在一定时间后进行重发,此时与TCP服务器建立连接,加入采用二握手的方式,接收到服务器的确认报文后之后,不在发送普通确认报文。在传输完数据之后,通过四次挥手释放连接。此时双方处于关闭连接状态。
注意此时就出现了问题,假如在第一次发送的TCP请求此时发送到达了TCP服务器,本来这是一个早已失效的报文段,但是服务器收到此失效的报文之后,会误认为是客户端再次发出的一个新的连接请求。
于是服务器就向客户端又发出确认报文,表示同意建立连接。此时服务器处于连接状态,而客户端由于处于关闭状态,不会接收该确认报文。
所以造成了TCP服务器会一直重发,造成了资源浪费。
练习
注意:
- TCP的标准规定,SYN=1的报文段不能携带数据,但要消耗掉一个序号。
- TCP的标准规定,普通的确认报文段如果不携带数据,则不消耗序号。
TCP连接的释放
概述
- TC通过四报文挥手来释放连接
四挥手释放连接过程
- 第一次挥手:客户端发送连接释放报文
TCP客户进程会发送TCP连接释放报文段,并进入终止等待1状态
TCP连接释放报文段首部中有以下关键数据位:
- 终止位FIN和确认位ACK:值都被设置为1,表明这是一个TCP连接释放报文段,同时也对之前收到的报文段进行确认
- 序号seq字段:值设置为u,u等于TCP客户进程之前已传送过的数据的最后一个字节的序号加1,用来表示发送过程中的最后一个字节序号为u
- 确认号ack字段:值设置为v,v等于服务器进程之前发送的数据中最后一个字节的序号加1,也就是确认收到已经收到的服务器发送的数据
注意:TCP规定终止位FIN等于1的报文段即使不携带数据,也要消耗掉一个序号
- 第二次挥手:TCP服务器发送确认请求
接收方再接收到连接释放报文后,会发送一个普通的TCP确认报文段并且进入关闭等待状态。
普通的TCP确认报文段首部中有以下关键数据位:
- 确认位ACK:值被设置为1,表明这是一个普通的TCP确认报文段。
- 序号seq:值设置为v,v等于TCP服务器进程之前已传送过的数据的最后一个字节的序号加1,与之前收到的TCP连接释放报文段中的确认号ack值匹配
- 确认号ack字段:值为u+1,这是对TCP连接释放报文段的确认,也就是为发送方连接释放报文中的seq的值+1。
- 在以上等待过程中,客户端会进入终止等待2,此时如果TCP服务器还有数据传输,则可以进行数据传输
- 第三次挥手:当服务器没有数据要传输后,进行第三次挥手
此时TCP服务器进程会发送TCP连接释放报文段并进入最后确认状态。
在该报文段中有以下关键数据段:
- 终止位FIN和确认位ACK:值都被设置为1,表明这是一个TCP连接释放报文段,同时也对之前收到的报文段进行确认。
- 序号seq:值为w,因为在半关闭状态下,TCP服务器进程可能又发送一段数据,因此w就是该段数据最后的序号。
- 确认号ack:值为u+1,这是对之前收到的TCP连接释放报文段的重复确认,因此值与发送方第一次挥手发送的seq值+1。
- 第四次挥手:TCP客户进程收到TCP连接释放报文段后开始第四次挥手
此时针对第三次挥手的报文段发送普通的TCP确认报文段,之后进入时间等待状态。
该报文段首部中有以下关键数据位:
- 确认位ACK:值被设置为1,表明这是一个普通的TCP确认报文段。
- 序号seq字段:值设置为u+1,用来表示最后一个发送的字节序号,但是为何没有发送数据,而此时值要设置为u+1(对比第一次挥手数据),因为TCP客户进程之前发送的TCP连接释放报文段(带有FIN)虽然不携带数据,但要消耗掉一个序号。
- 确认号ack:值设置为w+1,这是对所收到的TCP连接释放报文段的确认
- 此时,TCP服务器进程收到该报文段后就进入关闭状态,而TCP客户进程还要经过2MSL后才能进入关闭状态:
MSL具体的值可以根据TCP协议的不同实现进行设置。
客户端可以直接关闭连接吗?
不能。需要2MSL才关闭。
TCP保活定时器
TCP报文的首部格式
概述
- 为了实现可靠传输,TCP采用了面向字节流的方式。
- 在发送数据时,从发送缓存中取出一部分或者全部字节,并给其添加一个首部使之称为TCP报文段。
TCP首部和IP地址的首部类似,都由固定部分和扩展部分构成。和IP的格式相似,都有20字节的固定长度。
源端口和目的端口字段
举例
序号、确认号、ACK字段
图中例子序号为166,就是从166开始。
也就是ack字段。
举例
数据偏移字段
举例
其数据偏移二进制数的十进制表示 * 4 = 首部长度