MAC/IP/TCP/UDP头结构分析

目录

一、MAC帧头定义

二、IP头结构的定义

三、TCP头结构定义

四、UDP头结构的定义

一、MAC帧头定义
MAC帧是数据帧的一种。而所谓数据帧,就是数据链路层的协议数据单元,它包括三部分:帧头,数据部分,帧尾。其中,帧头和帧尾包含一些必要的控制信息,比如同步信息、地址信息、差错控制信息等;数据部分则包含网络层传下来的数据,比如ip数据包。

目前,有四种不同格式的以太网帧在使用,它们分别是:

Ethernet II即DIX 2.0:Xerox与DEC、Intel在1982年制定的以太网标准帧格式。Cisco名称为:ARPA。
Ethernet 802.3 raw:Novell在1983年公布的专用以太网标准帧格式。Cisco名称为:Novell-Ether。
Ethernet 802.3 SAP:IEEE在1985年公布的Ethernet 802.3的SAP版本以太网帧格式。Cisco名称为:SAP。
Ethernet 802.3 SNAP:IEEE在1985年公布的Ethernet 802.3的SNAP版本以太网帧格式。Cisco名称为:SNAP。
Ethernet II和IEEE802.3的帧格式比较类似,主要的不同点在于前者定义的2字节为包类型,而后者定义的2字节为的长度;所幸的是,后者定义的有效长度值与前者定义的有效类型值无一相同,这样就容易区分两种帧格式了。如果值大于 1500(0x05DC),说明是以太网类型字段,EthernetII 帧格式。如果值小于等于1500,说明是长度字段,IEEE802.3 帧格式。因此类型字段值最小的是 0x0600。而长度最大为 1500。

   MAC层要求定界字符之后的内容要在64字节到1518个字节之间,其中包括14字节的目标和源MAC,4字节的CRC32值。并且报文帧之间的传递间隔要大于9.6us。

 

 

        SFD---start frame delimeter   FSC: Frame chechk sequence(CRC)

类型字段 (2个字节): 用来标志上一层使用的是什么协议,以便把收到的MAC帧的数据上交给上一层的这个协议;数据字段 (46-1500): 正式名称是MAC客户数据字段最小长度64 字节-18字节的首部和尾部 = 数据字段的最小长度;FCS字段 (4 字节):当数据字段的长度小于 46 字节时,应在数据字段的后面加入整数字节的填充字段,以保证以太网的MAC帧长不小于64 字节;在帧的前面插入的 8 字节中的第一个字段共 7 个字节,是前同步码,用来迅速实现 MAC帧的比特同步。第二个字段是帧开始定界符,表示后面的信息就是MAC帧。

/*数据帧定义,头14个字节,尾4个字节*/
typedef struct _MAC_FRAME_HEADER
{
 char m_cDstMacAddress[6];    //目的mac地址
 char m_cSrcMacAddress[6];    //源mac地址
 short m_cType;            //上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp
}__attribute__((packed))MAC_FRAME_HEADER,*PMAC_FRAME_HEADER;
 
typedef struct _MAC_FRAME_TAIL
{
 unsigned int m_sCheckSum;    //数据帧尾校验和
}__attribute__((packed))MAC_FRAME_TAIL, *PMAC_FRAME_TAIL;

二、IP头结构的定义


/*IP头定义,共20个字节*/
typedef struct _IP_HEADER 
{
 char m_cVersionAndHeaderLen;       //版本信息(前4位),头长度(后4位)
 char m_cTypeOfService;            // 服务类型8位
 short m_sTotalLenOfPacket;        //数据包长度
 short m_sPacketID;              //数据包标识
 short m_sSliceinfo;               //分片使用
 char m_cTTL;                  //存活时间
 char m_cTypeOfProtocol;          //协议类型
 short m_sCheckSum;             //校验和
 unsigned int m_uiSourIp;          //源ip
 unsigned int m_uiDestIp;          //目的ip
} __attribute__((packed))IP_HEADER, *PIP_HEADER ;

版本(Version)字段:占4比特。用来表明IP协议实现的版本号,当前一般为IPv4,即0100。


报头长度(Internet Header Length,IHL)字段:占4比特。因为头部长度不固定(Option可选部分不固定),所以需要标识该分组的头部长度多少,用4bit表示,以4byte为单位,取值范围:5-15,即20(5*4)-60(15*4)byte(其他字段也是类似的计算方式,因为bit位是不够表示该字段的值) 


服务类型(Type of Service ,TOS)字段:占8比特。其中前3比特为优先权子字段(Precedence,现已被忽略)。第8比特保留未用。第4至第7比特分别代表延迟、吞吐量、可靠性和花费。当它们取值为1时分别代表要求最小时延、最大吞吐量、最高可靠性和最小费用。这4比特的服务类型中只能置其中1比特为1。可以全为0,若全为0则表示一般服务。服务类型字段声明了数据报被网络系统传输时可以被怎样处理。例如:TELNET协议可能要求有最小的延迟,FTP协议(数据)可能要求有最大吞吐量,SNMP协议可能要求有最高可靠性,NNTP(Network News Transfer Protocol,网络新闻传输协议)可能要求最小费用,而ICMP协议可能无特殊要求(4比特全为0)。实际上,大部分主机会忽略这个字段,但一些动态路由协议如OSPF(Open Shortest Path First Protocol)、IS-IS(Intermediate System to Intermediate System Protocol)可以根据这些字段的值进行路由决策。RFC2474的ToS取消了IP precedence字段而使用了DSCP,QoS里有描述,给QoS用来打标签。TOS字段历史:

总长度字段:占16比特。指明整个数据报的长度(以字节为单位,含头长度)。最大长度为65535字节。可用总长度减去头部长度获得实际报文数据的长度,取值范围0-65535byte,链路只允许1500byte,所以一般都需要MTU分片 。

标志字段:占16比特。用来唯一地标识主机发送的每一份数据报。通常每发一份报文,它的值会加1。通常与标记字段和分片偏移字段一起用于IP报文的分片。当原始报文大小超过MTU,那么就必须将原始数据进行分片。每个被分片的报文大小不得超过MTU,而这个字段还将在同一原始文件被分片的报文上打上相同的标记,以便接收设备可以识别出属于同一个报文的分片,“类似于进程号”,有时候电信会用他来识别流量是否是同一台主机(因为做了PAT后源ip都是一样的,鸡贼!)

注意:Ethernet以太网跟802.3以太网有所区别,802.3是由IEEE指定的标准,比较复杂用的比较少,网卡一般两种都支持。IP数据包的MTU值在各种物理线路环境下对应的MTU取值:(注意:不包含帧头和尾)

 

 

 

标志位字段:占3比特。标志一份数据报是否要求分段。第1位没有被使用。第2位D是不分片位(DF),Do not fragment,顾名思义,不要分片,当DF位设置为1时,表示路由器不能对报文进行分片处理。第3位M表示还有后继分片(MF),More fragment,多分片,当路由器对报分进行分片时,除了最后一个分片的MF位设置为0外,其他所有分片的MF位均设置1,以便接收者直到收到MF位为0的分片为止

 
段偏移字段:占13比特。如果一份数据报要求分段的话,此字段指明该段偏移距原始数据报开始的位置。
生存期(TTL:Time to Live)字段:占8比特。用来设置数据报最多可以经过的路由器数。由发送数据的源主机设置,通常为32、64(win7)、128、255(linux)等。每经过一个路由器,其值减1,直到0时该数据报被丢弃。

协议字段:占8比特。指明IP层所封装的上层协议类型,如ICMP(1)、IGMP(2) 、TCP(6)、UDP(17)等。


头部校验和字段:占16比特。内容是根据IP头部计算得到的校验和码。计算方法是:对头部中每个16比特进行二进制反码求和。(和ICMP、IGMP、TCP、UDP不同,IP不对头部后的数据进行校验)。
源IP地址、目标IP地址字段:各占32比特。用来标明发送IP数据报文的源主机地址和接收IP报文的目标主机地址。
可选项字段:占32比特。用来定义一些任选项:如记录路径、时间戳等。这些选项很少被使用,同时并不是所有主机和路由器都支持这些选项。可选项字段的长度必须是32比特的整数倍,如果不足,必须填充0以达到此长度要求。


 

三、TCP头结构定义

 


/*TCP头定义,共20个字节*/
typedef struct _TCP_HEADER 
{
 short m_sSourPort;              // 源端口号16bit
 short m_sDestPort;              // 目的端口号16bit
 unsigned int m_uiSequNum;         // 序列号32bit
 unsigned int m_uiAcknowledgeNum;  // 确认号32bit
 short m_sHeaderLenAndFlag;        // 前4位:TCP头长度;中6位:保留;后6位:标志位
 short m_sWindowSize;            // 窗口大小16bit
 short m_sCheckSum;              // 检验和16bit
 short m_surgentPointer;           // 紧急数据偏移量16bit
}__attribute__((packed))TCP_HEADER, *PTCP_HEADER;
/*TCP头中的选项数据部分定义
kind = 1表示 无操作NOP,无后面的部分
kind = 2表示 maximum segment,后面的Length就是maximum segment选项的长度(以byte为单位,1+1+内容部分长度)
kind =  3表示 windows scale,后面的Length就是 windows scale选项的长度(以byte为单位,1+1+内容部分长度)
kind =  4表示 SACK permitted    Length为2,没有内容部分
kind =  5表示这是一个SACK包     Length为2,没有内容部分
kind =  8表示时间戳,Length为10,含8个字节的时间戳
*/
typedef struct _TCP_OPTIONS
{
 char m_ckind;            //kind(8bit)
 char m_cLength;          //Length(8bit,整个选项的长度,包含前两部分)
 char m_cContext[32];     //内容(如果有的话)
}__attribute__((packed))TCP_OPTIONS, *PTCP_OPTIONS;
源端口:源端口和IP地址的作用是标识报文的返回地址。
目的端口:端口指明接收方计算机上的应用程序接口。TCP报头中的源端口号和目的端口号同IP数据报中的源IP与目的IP唯一确定一条TCP连接
序号和确认号:是TCP可靠传输的关键部分。序号是本报文段发送的数据组的第一个字节的序号。在TCP传送的流中,每一个字节一个序号。e.g.一个报文段的序号为300,此报文段数据部分共有100字节,则下一个报文段的序号为400。所以序号确保了TCP传输的有序性。确认号,即ACK,指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当ACK标志为1时才有效。比如建立连接时,SYN报文的ACK标志位为0。
数据偏移/首部长度:4bits。由于首部可能含有可选项内容,因此TCP报头的长度是不确定的,报头不包含任何任选字段则长度为20字节,4位首部长度字段所能表示的最大值为1111,转化为10进制为15,15*32/8 = 60,故报头最大长度为60字节。首部长度也叫数据偏移,是因为首部长度实际上指示了数据区在报文段中的起始偏移值。
保留:为将来定义新的用途保留,现在一般置0。
控制位:URG  ACK  PSH  RST  SYN  FIN,共6个,每一个标志位表示一个控制功能。
 URG:紧急指针标志,为1时表示紧急指针有效,为0则忽略紧急指针。
 ACK:确认序号标志,为1时表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段。
 PSH:push标志,为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。
 RST:重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求。
 SYN:同步序号,用于建立连接过程,在连接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1和ACK=1。
 FIN:finish标志,用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流。
窗口:滑动窗口大小,用来告知发送端接受端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口大小时一个16bit字段,因而窗口大小最大为65535。
校验和:奇偶校验,此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。由发送端计算和存储,并由接收端进行验证。
紧急指针:只有当 URG 标志置 1 时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。
选项和填充:最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍。
数据部分: TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。

四、UDP头结构的定义


/*UDP头定义,共8个字节*/
 
typedef struct _UDP_HEADER 
{
 unsigned short m_usSourPort;       // 源端口号16bit
 unsigned short m_usDestPort;       // 目的端口号16bit
 unsigned short m_usLength;        // 数据包长度16bit
 unsigned short m_usCheckSum;      // 校验和16bit
}__attribute__((packed))UDP_HEADER, *PUDP_HEADER;

端口号:用来表示发送和接受进程。由于 I P层已经把I P数据报分配给T C P或U D P(根据I P首部中协议字段值),因此T C P端口号由T C P来查看,而 U D P端口号由UDP来查看。T C P端口号与UDP端口号是相互独立的。
长度:UDP长度字段指的是UDP首部和UDP数据的字节长度。该字段的最小值为 8字节(发送一份0字节的UDP数据报是 O K)。
检验和:UDP检验和是一个端到端的检验和。它由发送端计算,然后由接收端验证。其目的是为了发现UDP首部和数据在发送端到接收端之间发生的任何改动。整个UDP报文头和UDP所带的数据的校验和(也包括伪报文头)。伪报文头不包括在真正的UDP报文头中,但是它可以保证UDP数据被正确的主机收到了。因在校验和中加入了伪头标,故ICMP除能防止单纯数据差错之外,对IP分组也具有保护作用。
 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值