udp头部数据结构

struct udphdr {
 __be16 source; //16位源端口号
 __be16 dest;  //16位目的端口号
 __be16 len;   //指udp首部长度和udp数据的长度总和长度

__sum16 check; //udp校验和,校验的是udp首部和upd数据的总的校验和
 
};

,由此知,16bit*4=64bit=8字节,udp首部长度8字节。

如果tcp和udp同时提供某种知名服务,两个协议通常选择相同的端口号,这纯粹是为了使用的方便,而不是协议本身规定的

tcp头部数据结构

struct tcphdr {
 __be16 source;      //16位源端口号
 __be16 dest;        //16位目的端口号

//每个tcp段都包源和目的端口号,用于寻找发送端和接受端的应用进程。这两个端口号加上ip报头中的源ip和目的ip,来确定一个唯一的TCP连接。
 __be32 seq;         //此次发送的数据在整个报文段中的起始字节数。此序号用来标识从tcp发送端向tcp接受端发送的数据字节流,seq表示在这个报文段中的第一个数据字节。如果将字节流看做在两个应用程序间的单向流动,则tcp用序号对每个字节进行计数。32 bit的无符号数。为了安全起见,它的初始值是一个随机生成的数,它到达2的32次方-1后又从零开始。
 __be32 ack_seq;     //是下一个期望接收的字节,确认序号应当是上次已成功接收的序号+1,只有ack标志为1时确认序号字段才有效。一旦一个连接已经建立了,ack总是=1
#if defined(__LITTLE_ENDIAN_BITFIELD)  //小端
 __u16 res1:4,  // 保留位
  doff:4,  //tcp头部长度,指明了在tcp头部中包含了多少个32位的字。由于options域的长度是可变的,所以整个tcp头部的长度也是变化的。4bit可表示最大值15,故15*32=480bit=60字节,所以tcp首部最长60字节。然后,没有任选字段,正常的长度是20字节
  fin:1, //发端完成发送任务
  syn:1, //同步序号用来发起一个连接
  rst:1, //重建连接
  psh:1, //接收方应该尽快将这个报文段交给应用层
  ack:1,  //一旦一个连接已经建立了,ack总是=1

urg:1,  //紧急指针有效
  ece:1, 
  cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
 __u16 doff:4,
  res1:4,
  cwr:1,
  ece:1,
  urg:1,
  ack:1,
  psh:1,
  rst:1,
  syn:1,
  fin:1;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif 
 __be16 window;   //窗口大小,单位字节数,指接收端正期望接受的字节,16bit,故窗口大小最大为16bit=1111 1111 1111 1111(二进制)=65535(十进制)字节
 __sum16 check;  //校验和校验的是整个tcp报文段,包括tcp首部和tcp数据,这是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证。
 __be16 urg_ptr;
};

所在头文件为/usr/src/linux/include/linux/ip.h,结构如下:
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD) //小端模式下
__u8 ihl:4,//首部长度(4位)
version:4;//ip协议版本IPv4
#elif defined (__BIG_ENDIAN_BITFIELD) //大端模式下
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 tos;//服务类型字段(8位)
__be16 -tot_len;//16位IP数据报总长度
__be16 -id;//16位标识字段(唯一表示主机发送的每一分数据报)
__be16 -frag_off;//(3位分段标志+13位分段偏移数)
__u8 ttl;//8位数据报生存时间
__u8 protocol;//协议字段(8位)
__be16 check;//16位首部校验和
__be32 saddr; //源IP地址
__be32 daddr; //目的IP地址
};
31 0
|----|----|------|--|-------------------|----------
|ver |ihl | -tos | -| tot_len |
|----|----|------|--|-------------------|
| id | frag_off -|
|---------|---------|-------------------|
| ttl |protocol | check | 20 Bytes
|---------|---------|-------------------|
| saddr |
|---------------------------------------|
| daddr |
|---------------------------------------|----------
| |
-| options | 40 Bytes
| |
|---------------------------------------|
IPv4 (Internel协议)头部
iphdr->version
版本(4位),目前的协议版本号是4,因此IP有时也称作IPv4。
iphdr->ihl
首部长度(4位):首部长度指的是IP层头部占32 bit字的数目(也就是IP层头部包含多少个4字节 -- 32位),包括任何选项。由于它是一个4比特字段,因此首部最长为60个字节。普通IP数据报(没有任何选择项)字段的值是5 <==> 5 * 32 / 8 = 5 * 4 = 20 Bytes
iphdr->tos
服务类型字段(8位): 服务类型(TOS)字段包括一个3 bit的优先权子字段(现在已被忽略),4 bit的TOS子字段和1 bit未用位但必须置0。4 bit的TOS子字段分别代表:最小时延、最大吞吐量、最高可靠性和最
小费用。4 bit中只能设置其中1 bit。如果所有4 bit均为0,那么就意味着是一般服务。
iphdr->tot_len
总长度字段(16位)是指整个IP数据报的长度,以字节为单位。利用首部长度字段和总长度字段,就可以知道 IP数据报中数据内容的起始位置和长度。由于该字段长16比特,所以IP数据报最长可达65535字节
总长度字段是IP首部中必要的内容,因为一些数据链路(如以太网)需要填充一些数据以达到最小长度。尽管以太网的最小帧长为46字节,但是IP数据可能会更短。如果没有总长度字段,那么IP层就不知道46字节中有多少是IP数据报的内容。
iphdr->id
标识字段(16位)唯一地标识主机发送的每一份数据报。通常每发送一份报文它的值就会加1。
iphdr->frag_off (16位)
frag_off域的低13位 -- 分段偏移(Fragment offset)域指明了该分段在当前数据报中的什么位置上。除了一个数据报的最后一个分段以外,其他所有的分段(分片)必须是8字节的倍数。这是8字节是基本分段单位。由于该域有13个位,所以,每个数据报最多有8192个分段。因此,最大的数据报长度为65,536字节,比iphdr->tot_len域还要大1。
iphdr->frag_off的高3位
(1) 比特0是保留的,必须为0;
(2) 比特1是“不分片”(DF -- Don't Fragment)标志,如果将这一比特置1,IP将不对数据报进行分片,这时如果有需要进行分片的数据报到来,会丢弃此数据报并发送一个ICMP差错报文给起始端。
(3) 比特2是“更多分片”(MF -- More Fragment)标志。除了最后一片外,其他每个组成数据报的片都要把该比特置1。
|---|-------------|
|DM0| offset |
|---|-------------|
15 1312 0
iphdr->ttl
TTL(time-to-live) -- 8位,生存时间字段设置了数据报可以经过的最多路由器数。它指定了数据报的生存时间。TTL的初始值由源主机设置(通常为32或64),一旦经过一个处理它的路由器,它的值就减去1。当该字段的值为0时,数据报就被丢弃,并发送ICMP报文通知源主机。
TTL(Time to live)域是一个用于限制分组生存期的计数器。这里的计数时间单位为秒,因此最大的生存期为255秒。在每一跳上该计数器必须被递减,而且,当数据报在一台路由器上排队时间较长时,该计数器必须被多倍递减。在实践中,它只是跳计数器,当它递减到0的时候,分组被丢弃,路由器给源主机发送一个警告分组。此项特性可以避免数据报长时间地逗留在网络中,有时候当路由表被破坏之后,这种事情是有可能发生的。
iphdr->protocol
协议字段(8位): 根据它可以识别是哪个协议向IP传送数据。
当网络层组装完成一个完整的数据报之后,它需要知道该如何对它进行处理。协议(Protocol)域指明了该将它交给哪个传输进程。TCP是一种可能,但是UDP或者其他的协议也是可能的。
iphdr->check
首部检验和字段(16位)是根据IP首部计算的检验和码。它不对首部后面的数据进行计算。 ICMP、IGMP、UDP和TCP在它们各自的首部中均含有同时覆盖首部和数据检验和码。
为了计算一份数据报的IP检验和,首先把检验和字段置为0。然后,对首部中每个16 bit进行二进制反码求和(整个首部看成是由一串16 bit的字组成),结果存在检验和字段中。当收到一份IP数据报后,同样对首部中每个16 bit进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该为全1。如果结果不是全1(即检验和错误),那么IP就丢弃收到的数据报。但是不生成差错报文,由上层去发现丢失的数据报并进行重传。
iphdr->saddr
32位源IP地址
iphdr->daddr
32位目的IP地址
网络字节序
4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31 bit。这种传输次序称作big endian字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。

不同的CPU有不同的字节序类型 这些字节序是指整数在内存中保存的顺序 这个叫做主机序 
最常见的有两种
1. Little endian:将低序字节存储在起始地址
2. Big endian:将高序字节存储在起始地址

LE little-endian 
最符合人的思维的字节序 
地址低位存储值的低位 
地址高位存储值的高位 
怎么讲是最符合人的思维的字节序,是因为从人的第一观感来说 
低位值小,就应该放在内存地址小的地方,也即内存地址低位 
反之,高位值就应该放在内存地址大的地方,也即内存地址高位

BE big-endian 
最直观的字节序 
地址低位存储值的高位 
地址高位存储值的低位 
为什么说直观,不要考虑对应关系 
只需要把内存地址从左到右按照由低到高的顺序写出 
把值按照通常的高位到低位的顺序写出 
两者对照,一个字节一个字节的填充进去

例子:在内存中双字0x01020304(DWORD)的存储方式

内存地址 
4000 4001 4002 4003 
LE 04 03 02 01 
BE 01 02 03 04

例子:如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
      big-endian  little-endian
0x0000  0x12      0xcd
0x0001  0x23      0xab
0x0002  0xab      0x34
0x0003  0xcd      0x12
x86系列CPU都是little-endian的字节序.

网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。

为了进行转换 bsd socket提供了转换的函数 有下面四个
htons 把unsigned short类型从主机序转换到网络序
htonl 把unsigned long类型从主机序转换到网络序
ntohs 把unsigned short类型从网络序转换到主机序
ntohl 把unsigned long类型从网络序转换到主机序

在使用little endian的系统中 这些函数会把字节序进行转换 
在使用big endian类型的系统中 这些函数会定义成空宏

同样 在网络程序开发时 或是跨平台开发时 也应该注意保证只用一种字节序 不然两方的解释不一样就会产生bug.

注:
1、网络与主机字节转换函数:htons ntohs htonl ntohl (s 就是short l是long h是host n是network)
2、不同的CPU上运行不同的操作系统,字节序也是不同的,参见下表。
处理器    操作系统    字节排序
Alpha    全部    Little endian
HP-PA    NT    Little endian
HP-PA    UNIX    Big endian
Intelx86    全部    Little endian <-----x86系统是小端字节序系统
Motorola680x()    全部    Big endian
MIPS    NT    Little endian
MIPS    UNIX    Big endian
PowerPC    NT    Little endian
PowerPC    非NT    Big endian  <-----PPC系统是大端字节序系统
RS/6000    UNIX    Big endian
SPARC    UNIX    Big endian
IXP1200 ARM核心    全部    Little endian

数据包头分析---网络字节序与主机字节序相关推荐

  1. linux网络编程一:主机字节序与网络字节序的的判断

     linux网络编程一:主机字节序与网络字节序的的判断(1)现代CPU的累加器一次能装载至少4字节(32位),即一个整数.那么这4字节在内存中排列的顺序将影响它被累加器装载成的整数值,这就是字节序问题 ...

  2. php 字节序,Linux_Linux中网络字节序和主机字节序,主机字节序就是我们平常说的 - phpStudy...

    Linux中网络字节序和主机字节序 主机字节序就是我们平常说的大端和小端模式:不同的 CPU 有不同的字节序类型,这些字节序是指整数在内存中保存的顺序 这个叫做主机序.Big-Endian和Littl ...

  3. java 网络字节序转主机字节序_C语言高级编程——网络编程技术

    了解什么是网络编程 熟悉七层网络模型 熟悉网络开发中使用到的函数 掌握TCP协议类程序开发 掌握UDP协议类程序开发 计算机本身是不会进行网络通信的,所以要想使通过软件进行网络通信,必须制定相应的规则 ...

  4. 网络字节序与主机字节序的相互转换

    1.网络字节序与主机字节序 在Linux网络编程中,经常碰到网络字节序与主机字节序的相互转换.说到网络字节序与主机字节序需要清晰了解以下几个概念. 字节序,顾名思义,指字节在内存中存储的顺序.比如一个 ...

  5. 网络字节序和主机字节序

    网络字节序说明 TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节.例如上一节的UDP段格式,地址0-1是16位的源端口号,如果这个端口号是1000(0x3e8),则地址0是0x03,地 ...

  6. java转网络字节序_【转】网络字节序与主机字节序

    最近在项目开发过程中,需要在采用JAVA作为语言的服务器与采用C++作为语言的服务器间进行通信,这就涉及到这两种语言间数据类型的转换以及网络字节序与主机字节序的区别.该文主要说说网络字节序和主机字节序 ...

  7. C#之网络字节序与主机字节序互转

    主机字节序转网络字节序 //加上两个字节长度,再发送byte[] bSend = new byte[buffer.Length + 2]; byte[] bLenth = BitConverter.G ...

  8. 网络字节序和主机字节序互转

    1.网络字节序转为主机字节序 //网络字节序转为主机字节序 uint64_t utils::Ntohll(uint64_t val) {if (__BYTE_ORDER == __LITTLE_END ...

  9. 【转】大端模式与小端模式、网络字节顺序与主机字节顺序 (经典)

    大端模式与小端模式 一.概念及详解 在各种体系的计算机中通常采用的字节存储机制主要有两种: big-endian和little-endian,即大端模式和小端模式. 先回顾两个关键词,MSB和LSB: ...

最新文章

  1. 优化webpack配置
  2. 2016/01/13开始学习git:分支管理:Bug分支
  3. 构造函数初始化结构体
  4. router3 BGP2 属性及选路
  5. hdu-5068 Harry And Math Teacher
  6. swift5.5异常的处理的三种的方式
  7. java 从excel中读取数据_java如何从excel中读出数据
  8. display: inline-block;水平居中
  9. MySQL无中心化集群_MySQL Plus 如何做到无中心化、数据强一致性、秒级切换?
  10. C语言_顺序结构的程序设计
  11. s905各种型号的区别_2020榨汁机推荐,榨汁机、原汁机和破壁机有什么区别?高性价比榨汁机、原汁机怎么选?...
  12. micropython和python区别-选择C/C++还是选择MicroPython来开发?(第0章-第三节)
  13. 如何在 Mac 上的“音乐”应用和 iTunes 中创建 Genius 播放列表?
  14. 面试小题,传入6返回9,传入9返回6
  15. python 读取文件名列表_python 读取指定文件夹下所有文件名
  16. xshell xftp免费版下载
  17. 暗黑破坏神(DIABLOII 1.11B)BOT 及源代码公开下载
  18. 小学六年级下册计算机计划,小学信息技术六年级下册教学计划
  19. 运维的升级打怪之路v2版
  20. matplotlib 画图总结

热门文章

  1. 组件的高可用性 High Availability
  2. Report Studio值提示通过prompt宏函数给sql查询传参
  3. gitlab升级-(一)安装一台旧版本
  4. Linux对称NAT的UDP穿越
  5. Centos7下安装部署oracle数据库方法及问题汇总
  6. 云视频通信在建筑施工企业的应用
  7. 用基本控件简单地仿QQ登录界面
  8. jQuery方法position()与offset()区别
  9. 错误中积累经验,BUG中寻发展,总结中提升
  10. 用SVN下载编译Spring3.2.4源码导入eclipse