标签:字节 传输 首部 08 TCP 发送 TCP01 传输层 数据
TCP—数据格式
◼ 数据偏移
占4位,取值范围是0x0101~0x1111
乘以4:首部长度(Header Length)
首部长度是20~60字节,可选字节最大是40字节
为什么取名叫数据偏移
数据往右边偏移,首部长度多少,数据就往右边偏移多少。
◼ 保留
占6位,目前全为0
因为没什么用
TCP—小细节
◼ 有些资料中,TCP首部的保留(Reserved)字段占3位,标志(Flags)字段占9位,Wireshark也是这么认为。
因为9位标志位的前三位也是没有用的,也算是保留位,所以有的标6位
主要是为了保证首部是4的倍数。
TCP — 一个细节
◼ UDP的首部中有个16位的字段记录了整个UDP报文段的长度(首部+数据)
◼ 但是,TCP的首部中仅仅有个4位的字段记录了TCP报文段的首部长度,并没有字段记录TCP报文段的数据长度
◼ 分析
UDP首部中占16位的长度字段是冗余的,因为首部固定是8字节,全为0都没有什么影响,纯粹是为了保证首部是32bit对齐(字节是4的倍数)
TCP\UDP的数据长度,完全可以由IP数据包的首部推测出来
✓ 传输层的数据长度 = 网络层的总长度 – 网络层的首部长度 – 传输层的首部长度
没有必要用首部的字段去标记数据长度
TCP — 检验和(Checksum)
◼ 跟UDP一样,TCP检验和的计算内容:伪首部 + 首部 + 数据
伪首部:占用12字节,仅在计算检验和时起作用,并不会传递给网络层
红色圈起来的三行就是伪首部
为什么TCP首部要搞的这么复杂,因为它要保证可靠传输、流量控制、拥塞控制。
可靠传输:假设服务器要发送大量的数据,它不可能一次性发过去,它得分成好几段,中间弄丢了 ,可以再发送给你,保证你收到数据一定是完整的。
流量控制:客户端发送数据给服务器,顺便告诉了服务器,客户端窗口接收的大小,传输层有一个缓存,用来接收服务器发过来的数据包,随着服务器不断发包过来,缓存逐渐变小或者网络情况不好,这个时候就会告诉服务器,我现在接收窗口的大小,让它根据情况来发。
TCP—标志位(Flags)
◼ URG(Urgent)
当URG=1时,紧急指针字段才有效。表明当前报文段中有紧急数据,应优先尽快传送
如果URG=0,紧急指针放什么都没用;
紧急指针存储多少,就代表TCP数据部分就有多少位是紧急数据
◼ ACK(Acknowledgment)
当ACK=1时,确认号字段才有效
◼ PSH(Push)
一般我们用不上,它是用在交互式网络上面
◼ RST(Reset)
当RST=1时,表明连接中出现严重差错,必须释放连接,然后再重新建立连接
RST=1时,wireshark数据流标深红色
◼ SYN(Synchronization)
当SYN=1、ACK=0时,表明这是一个建立连接的请求
TCP三次握手,第一次建立连接请求
若对方同意建立连接,则回复SYN=1、ACK=1
第二次同意建立连接
◼ FIN(Finish)
当FIN=1时,表明数据已经发送完毕,要求释放连接
TCP—序号、确认号、窗口
◼ 序号(Sequence Number)
占4字节
首先,在传输过程的每一个字节都会有一个编号
在建立连接后,序号代表:这一次传给对方的TCP数据部分的第一个字节的编号
假设服务器数据部分返回很多数据,对数据的字节进行编码,这个时候我们会分段发,多个字节合在一起,数据部分会有一个TCP首部,首部里面有一个序号,序号就是这一次传给对方的TCP数据部分的第一个字节的编号
◼ 确认号(Acknowledgment Number)
占4字节
在建立连接后,确认号代表:期望对方下一次传过来的TCP数据部分的第一个字节的编号,同时确认之前的数据已经接收到了
◼ 窗口(Window)
占2字节
这个字段有流量控制功能,用以告知对方下一次允许发送的数据大小(字节为单位)
TCP—可靠传输—停止等待ARQ协议
◼ ARQ(Automatic Repeat–reQuest),自动重传请求
只要发送端迟迟没有收到确认,经过一定的时间,就会超时重传
如果数据量大,假设为1000字节,分成10段,一段为一秒,效率非常低下。
疑问
◼ 若有个包重传了N次还是失败,会一直持续重传到成功为止么?
这个取决于系统的设置,比如有些系统,重传5次还未成功就会发送reset报文(RST)断开TCP连接
TCP—可靠传输— 连续ARQ协议+ 滑动窗口协议
◼ 如果接收窗口最多能接收4个包
但发送方只发了2个包
◼ 接收方如何确定后面还有没有2个包?
等待一定时间后没有第3个包
就会返回确认收到2个包给发送方
按照顺序发送,最后一个接收到的是M4,告诉对方我收到了M4,相当于告诉对方,我前面的全收到了,对方就会发送M4后面的。
发送方的窗口大小由接收方的窗口决定。
◼ 现在假设每一组数据是100个字节,代表一个数据段的数据
◼ 每一组给一个编号
TCP—可靠传输 — SACK(选择性确认)
◼ 在TCP通信过程中,如果发送序列中间某个数据包丢失(比如1、2、3、4、5中的3丢失了)
◼ TCP会通过重传最后确认的分组后续的分组(最后确认的是2,会重传3、4、5)
◼ 这样原先已经正确传输的分组也可能重复发送(比如4、5),降低了TCP性能
◼ 为改善上述情况,发展出了SACK(Selective acknowledgment,选择性确认)技术
告诉发送方哪些数据丢失,哪些数据已经提前收到
使TCP只重新发送丢失的包(比如3),不用发送后续所有的分组(比如4、5)
TCP—可靠传输— SACK(选择性确认)
◼ SACK信息会放在TCP首部的选项部分
Kind:占1字节。值为5代表这是SACK选项
Length:占1字节。表明SACK选项一共占用多少字节
Left Edge:占4字节,左边界
Right Edge:占4字节,右边界
通过范围来进行确认
◼ 一对边界信息需要占用8字节,由于TCP首部的选项部分最多40字节,所以SACK选项最多携带4组边界信息
Kind、Length是刚需,占用两个字节,剩下38,除以边界字节,为4(38/8=4)
超过4组,只能重传了
SACK选项的最大占用字节数 = 4 * 8 + 2 = 34
思考一个问题
◼ 为什么选择在传输层就将数据“大卸八块”分成多个段,而不是等到网络层再分片传递给数据链路层?
因为可以提高重传的性能
需要明确的是:可靠传输是在传输层进行控制的
✓ 如果在传输层不分段,一旦出现数据丢失,整个传输层的数据都得重传
✓ 如果在传输层分了段,一旦出现数据丢失,只需要重传丢失的那些段即可
实例演示
窗口接收的数据大小
序号的原生值-序号的相对值=
相同请求的唯一标识
wirshark知道唯一标识、序号的原生值,序号的相对值是他算出来的,不是首部标的。
相同请求的唯一标识跟刚开始建立连接的序号和确认号有非常大的关系
文件传输的讲解
先建立TCP三次连接,客户端发送HTTP请求,告诉服务器,我要下载什么文件,把请求头和请求体加上一些乱七八糟的发送给服务器,由于文件太大了,服务器在传输层根据对方的窗口拆开成一片片发送,一层层封装,到了客户端,在一层层解封,到了传输层,就把他们拼接成一份完整的文件,给应用层。
数据在传输层就已经拆的很干净了,大小就没有超过1400的,不用考虑在网络层在拆。
为什么服务器发送了一连串的748
服务器传给客户端的ACK,是期望客户端发送给服务器序号为748的数据,因为这中间的过程客户端一直没有给服务器发送数据,所以服务器一直没有收到数据序号为748的数据,才一直在发ACK,等服务器发送完这一波窗口之后,客户端就发送了序号为748的数据。
标签:字节,传输,首部,08,TCP,发送,TCP01,传输层,数据 来源: https://blog.csdn.net/m0_53008479/article/details/120683169
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。