Tcpip报⽂解析
在编写⽹络程序时,常使⽤TCP协议。那么⼀个tcp包到底由哪些东西构成的呢?其实⼀个TCP包,⾸先需要通过IP协议承载,⽽IP报⽂,⼜需要通过以太⽹传送。下⾯我们来看看⼏种协议头的构成
⼀ .Ethernet头
以太帧分好⼏种类型,常见的以太帧为Ethernet II
下⾯就是⼀个典型的Ethernet II帧
Ethernet II类型以太⽹帧的最⼩长度为64字节(6+6+2+46+4),最⼤长度为1518字节(6+6+2+1500+4)
⾸先是⽬的MAC 6个字节,然后源MAC6个字节,接下来数据类型两个字节。
常见的类型如下
IPv4: 0x0800
ARP:0x0806
PPPoE:0x8864
802.1Q tag: 0x8100
IPV6: 0x86DD
MPLS Label:0x8847
然后是数据长度,46-1500字节。对于不定长的数据包,帧最后还有4个字节的FCS(Frame check sequence)
下⾯是⼀个以太帧头⽰例,该报⽂类型为IPv4(0x8000)
⼆ IP头部
对于⼀个IPv4类型的以太帧,数据的开始就是IP头部。⼀般IPv4的头部是20个字节。
版本号(Version):4bit。表明IP协议的版本号。⼀般为0100(IPv4),0110(IPv6)
IP包头长度(Header Length):4bit。⽤于描述IP包头长度,因为IP包头长度是可变的。
这⾥所指⽰的长度,是以4个字节为⼀个单位。例如,⼀个IP包头的长度最长为“1111”,即15*4=60个字节。IP包头最⼩长度为20字节。
服务类型(Type of Service):长度8⽐特。
IP包总长(Total Length):16bit。以字节为单位计算的IP包的长度 (包括头部和数据),所以IP包最⼤长
度65535字节。
标识符(Identifier):16bit。该字段和Flags和Fragment Offest字段联合使⽤,对较⼤的上层数据包进⾏分段(fragment)操作。路由器将⼀个包拆分后,所有拆分开的⼩包被标记相同的值,以便⽬的端设备能够区分哪个包属于被拆分开的包的⼀部分。
标记(Flags):3bit。第⼀位是保留位不使⽤。第⼆位是DF(Don't Fragment)位,DF位设为1时表明路由器不能对该数据包分包。如果⼀个数据包⽆法在不分段的情况下发送,则路由器会丢弃该数据包并返回⼀个错误信息。第三位是MF(More Fragments)位,当路由器对⼀个上层数据包分
段,则路由器会在除了最后⼀个分段的IP包的包头中将MF位设为1。
⽚偏移(Fragment Offset):13bit。表⽰该IP包在该组分⽚包中位置,接收端靠此来组装还原IP包。
⽣存时间(TTL):8bit。当IP包在⽹络上传送时,每经过⼀个路由器,TTL就⾃动减⼀。值为0时,则丢弃报⽂。防⽌报⽂进⼊环路
协议(Protocol):8bit。标识IP头后⾯的报⽂协议类型
以下是⽐较常⽤的协议号:
1    ICMP
2    IGMP
6    TCP
17    UDP
88    IGRP
89    OSPF
头校验和(Header Checksum):16bit。⽤来做IP头部的正确性检测,但不包含数据部分。由于路由器会改变TTL,所以路由器会为每个通过的数据包重新计算这个值。
源和⽬的地址(Source and Destination Addresses):这两个地段都是32⽐特。标识了这个IP包的起源和⽬标地址。要注意除⾮使⽤NAT,否则整个传输的过程中,这两个地址不会改变。
下图就是⼀个IP头的内容
三 TCP 头部
TCP封装在IP报⽂中的时候,如下图所⽰,TCP头紧接着IP头(IPV6有扩展头的时候,则TCP头在扩展头后⾯),不携带选项(option)的TCP头长为
tcpip协议中基于tcp协议的应用程序20bytes,携带选项的TCP头最长可到60bytes。
源端⼝(Source Port):16bit, 表⽰报⽂发送⽅的端⼝号
⽬的端⼝(Destination port): 16bit,表⽰报⽂接收⽅的端⼝号
序列号(SN):32bit,标识了TCP报⽂中第⼀个byte在对应⽅向的传输中对应的字节序号。当SYN出现,序列码实际上是初始序列码(ISN),⽽第⼀个数据字节是ISN+1,单位是byte。⽐如发送端发送的⼀个TCP包净荷(不包含TCP头)为12byte,SN为5,则发送端接着发送的下⼀个数据包的时候,SN应该设置为5+12=17。通过系列号,TCP接收端可以识别出重复接收到的TCP包,从⽽丢弃重复包,同时对于乱序数据包也可以依靠系列号进⾏重排序,进⽽对⾼层提供有序的数据流。另外SYN标志和FIN标志在逻辑上也占⽤⼀个byte,当SYN标志位有效的时候,该字段也称为ISN(initial sequence number),详细请参考后续的TCP连接管理。
应答号(ACK):32bit,标识了报⽂发送端期望接收的字节序列。如果设置了ACK控制位,这个值表⽰⼀个准备接收的包的序列码,注意是准备接收的包,⽐如当前接收端接收到⼀个净荷为12byte的数据包,SN为5,则发送端可能会回复⼀个确认收到的数据包,如果这个数据包之前的数据也都已经收到了,这个数据包中的ACK Number则设置为12+5=17,表⽰17byte之前的数据都已经收到了。在举⼀个例⼦,如果在这个数据包之前有个SN为3,净荷为2byte的数据包丢失,则在接受端接收到这个SN为5的乱序数据包的时候,协议要求接收端必须要回复⼀个ACK确认包,这个确认包中的Ack Number只能设置为3。
头长(Header Length):4bit,指⽰TCP头的长度,即数据从何处开始。最⼤为15,单位是32⽐特,即4个字节,与IP头中的长度定义相同。
保留(Reserved):4bit,这些位必须是0。为了将来定义新的⽤途所保留,其中RFC3540将Reserved字段中的最后⼀位定义为Nonce标志。
标志(Code Bits):8bit
CWR(Congestion Window Reduce):拥塞窗⼝减少标志被发送主机设置,⽤来表明它接收到了设置ECE标志的TCP包,发送端将通过降低发送窗⼝的⼤⼩来降低发送速率
ECE(ECN Echo):ECN响应标志被⽤来在TCP3次握⼿时表明⼀个TCP端是否具备ECN功能,并且表明接收到的TCP包的IP头部的ECN被设置为11。更多信息请参考RFC793。
URG(Urgent):表⽰紧急(The urgent pointer) 指针是否有效。
ACK(Acknowledgment):1表⽰这是⼀个确认的TCP包, 0则不是确认包。
PSH(Push):该标志置位时,⼀般是表⽰发送端缓存中已经没有待发送的数据,接收端不将该数据进⾏队列处理,⽽是尽可能快将数据转由应⽤处理。
RST(Reset):⽤于复位相应的TCP连接。通常在发⽣异常或者错误的时候会触发复位TCP连接。
SYN(Synchronize):表⽰同步序列编号(Synchronize Sequence Numbers)是否有效。该标志仅在三次握⼿建⽴TCP连接时有效。它提⽰TCP连接的服务端检查序列编号,该序列编号为TCP连接发起端(⼀般是客户端)的初始序列编号。在这⾥,可以把TCP序列编号看作是⼀个范围从0到
4,294,967,295的32位计数器。通过TCP连接交换的数据中每⼀个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第⼀个字节的序列编号。
FIN(Finish):带有该标志置位的数据包⽤来结束⼀个TCP会话,但对应端⼝仍处于开放状态,准备接收后续数据。当FIN标志有效的时候我们称呼这个包为FIN包。
窗⼝⼤⼩(Window Size):16bit,表⽰从Ack Number开始还能接收多少字节的数据量,即当前接收端的接收窗⼝还有多少剩余空间。⽤于TCP的流量控制。
校验和(Checksum):16bit。发送端基于数据内容计算⼀个数值,接收端要与发送端数值结果完全⼀样,才能证明数据的有效性。接收端checksum校验失败的时候会直接丢掉这个数据包。CheckSum是根据伪头+TCP头+TCP数据三部分进⾏计算的。
紧急指针(Urgent  Pointer):16位,在URG标志设置了时才有效。与序号字段的值相加后表⽰最后⼀
个紧急数据的下⼀字节的序号,可以说这个字段是紧急指针相对当前序号的偏移。
选项(Option):长度不定,但长度必须以是32bits的整数倍。常见的选项包括MSS、SACK、Timestamp等等,后续的内容会分别介绍相关选项。
⼀个完整的TCP头展⽰

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。