在如何封装一个数据包上,是一个非常细致的问题,而利用UDP协议来封装的话,是比较简单,让我们一步步来分析典型的TCP/IP协议。一般来说一个典型的一个数据包,包括以太网MAC头+网络层IP数据头+传输层UDP头+要传输的数据。让我们一层层来看看这些数据头是如何构成的。

  

1、以太网MAC头

  一般情况下,以太网MAC头由14个字节构成,12个自己的MAC地址+上层协议的标识符。举个例子

  如果你要发送的目标MAC位00:1d:09:10:d1:9c,而你的MAC地址为01:60:6e:11:02:0f,上层一般都是网络层,即为IP层,IP层的标识符为0x8000,那么你的以太网MAC头就为

  00 1d 09 10 d1 9c 01 60 6e 11 02 0f 80 00.

  下面是更详细的解释,引用http://blog.csdn.net/louiswang2009/archive/2010/05/04/5554524.aspx这片博客。

  8字节的前导用于帧同步,CRC域用于帧校验。这些用户不必关心其由网卡芯片自动添加。目的地址和源地址是指网卡的物理地址,即MAC地址,具有唯一性。帧类型或协议类型是指数据包的高级协议,如 0x0806表示ARP协议,0x0800表示IP协议等。  

2、网络层IP头

  0x45, 0x00, IPlenght_h, IPlenght_l,

  0x00, 0x00, 0x00, 0x00, 0x80, 0x11,

  IPchecksum4, IPchecksum5,

   IPsource_1, IPsource_2, IPsource_3, IPsource_4,IPdestination_1, IPdestination_2, IPdestination_3, IPdestination_4

  上面是一个简单的ip头的例子,下面一个个的来解释啊!

  0x45,其中的高位0x4,表示的是版本号,ipv4的意思,而后面低字节5表示的是指明IPv4协议包头长度的字节数包含多少个32位,这里是5,也就是说协议头是5*4=20个字节的大小。

  0x00,定义IP封包在传送过程中要求的服务类型,如果所有4bit均为0,那么就意味着是一般服务,具体如下:

    ◆000..... (Routine): 过程字段,占3位。设置了数据包的重要性,取值越大数据越重要,取值范围为:0(正常)~ 7(网络控制)

    ◆...0....(Delay):延迟字段 ,占1位,取值:0(正常)、1(期特低的延迟)

    ◆....0...(Throughput):流量字段,占1位。取值:0(正常)、1(期特高的流量)

    ◆.....0..(Reliability) :可靠性字段,占1位。取值:0(正常)、1(期特高的可靠性)

    ◆…..0.(ECN-Capable Transport):显式拥塞指示传输字段,占1位。由源端设置,以显示源端节点的传输协议是支持ECN(Explicit Cogestion Notifica tion,显式拥塞指示)的。取值:0(不支持ECN)、1(支持ECN)

    ◆.......0(Congestion Experienced):拥塞预警字段,占1位。取值:0(正常,不拥塞)、1(拥塞)

  IPlenght_h, IPlenght_l,表示的是包总长度=IP头长度+UDP头长度+数据长度,最后讲长度分为高8位和低8位。

  0x00, 0x00,是上面的标志位,16个字节。每一个IP封包都有一个16位的唯一识别码。当程序产生的数据要通过网络传送时都会被拆散成封包形式发送,当封包要进行重组的时候这个ID就是依据了。

  0x00, 0x00这16位是由两部分组成,包括3bit的标记位和13bit的分段偏移量。

    这是当封包在传输过程中进行最佳组合时使用的3个bit的识别记号。占3位。

    ◆000(Reserved Fragment):保留分段。当此值为0的时候表示目前未被使用。

    ◆.0.(Don't Fragment):不分段。当此值为0的时候表示封包可以被分段,如果为1则不能被分割。

    ◆..0( More Fragment):更多分段。当上一个值为0时,此值为0就示该封包是最後一个封包,如果为1则表示其後还有被分割的封包。

    IP协议头格式规定当封包被分段之后,由于网路情况或其它因素影响其抵达顺序不会和当初切割顺序一至,所以当封包进行分段的时候会为各片段做好定位记录,以便在重组的时候就能够

    对号入座。值为多少个字节,如果封包并没有被分段,则FO值为“0"。 占13位。

  0x80表示生存时间。生存时间字段设置了数据报可以经过的最多路由器数,表示数据包在网络上生存多久。TTL的初始值由源主机设置(通常为32或64),一旦经过一个处理它的路由器,它的值就减去1。当该字段的值为0时,数据报就被丢弃,并发送ICMP消息通知源主机。这样当封包在传递过程中由於某些原因而未能抵达目的地的时候就可以避免其一直充斥在网路上面。占8位。

  0x11表示的是传输层的协议。如下表所示:

  IPchecksum4, IPchecksum5这两个是头校验和的高8位和低8位。

  指IPv4数据报包头的校验和。这个数值用来检错用的,用以确保封包被正确无误的接收到。当封包开始进行传送后,接收端主机会利用这个检验值会来检验余下的封包,如果一切无误就会发出确认信息表示接收正常。与UDP和TCP协议包头中的校验和作用是一样的。占16位。

  首部检验和字段是根据IP首部计算的检验和码,不对首部后面的数据进行计算。ICMP、IGMP、UDP和TCP协议在它们各自的首部中均含有同时覆盖首部和数据检验和码。

  IP协议头格式规定了:计算一份数据报的IP检验和,首先把检验和字段置为0。然后,对首部中每个16位进行二进制反码求和(整个首部看成是由一串16位的字组成),结果存在检验和字段中。当接收端收到一份IP数据报后,同样对首部中每个16 位进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该为全1。如果结果不是全1(即检验和错误),那么IP就丢弃收到的数据报。但是不生成差错消息,由上层去发现丢失的数据报并进行重传。

  ICMP、IGMP、UDP和TCP都采用相同的检验和算法,尽管TCP和UDP除了本身的首部和数据外,在IP首部中还包含不同的字段。由于路由器经常只修改TTL字段(减1),因此当路由器转发一份消息时可以增加它的检验和,而不需要对IP整个首部进行重新计算。

   IPsource_1, IPsource_2, IPsource_3, IPsource_4,IPdestination_1, IPdestination_2, IPdestination_3, IPdestination_4这两个就表示了源IP和目标IP。

3、UDP数据头

0x04, 0x00,0x04, 0x00, lenght_h, lenght_l, 0x00, 0x00  

  0x04, 0x00表示的是UDP的源端口,这里为1024;

  0x04, 0x00表示的是UDP的目标端口,这里为1024;

  lenght_h, lenght_l,为整个数据包的长度,包括MAC头+ip头+UDP头+校验位。

  0x00, 0x00这些是UDP协议的选项和填充位。

  这两个选项较少使用,只有某些特殊的封包需要特定的控制才会利用到。这些选项通常包括:

  ◆安全和处理限制:用于军事领域

  ◆记录路径:让每个路由器都记下它的IP地址

  ◆时间戳:让每个路由器都记下它的IP地址和时间

  ◆宽松的源站选路:为数据报指定一系列必须经过的IP地址

  ◆严格的源站选路:与宽松的源站选路类似,但是要求只能经过指定的这些地址,不能经过其他的地址。

  以上这些选项很少被使用,而且并非所有的主机和路由器都支持这些选项。

 总结:

  上面是对一个UDP封装数据的总结,便于以后更好的记忆。

http://www.cnblogs.com/yingfang18/archive/2010/11/29/1890831.html

如何利用UDP协议封装一个数据包的更多相关文章

  1. sk_buff封装和解封装网络数据包的过程详解(转载)

    http://dog250.blog.51cto.com/2466061/1612791 可以说sk_buff结构体是Linux网络协议栈的核心中的核心,几乎所有的操作都是围绕sk_buff这个结构体 ...

  2. sk_buff封装和解封装网络数据包的过程详解

    转自:http://www.2cto.com/os/201502/376226.html 可以说sk_buff结构体是Linux网络协议栈的核心中的核心,几乎所有的操作都是围绕sk_buff这个结构体 ...

  3. Lwip lwip_recvfrom函数一个数据包不能分多次读取。

    最近在写一个基于Lwip协议栈的网络程序,对于一包数据,想先获得包头信息,再根据包头信息读取后面的数据,但是调用recvfrom后,发现读取后面的数据读取不到,进一步查阅发现,原来对于UDP协议,一次 ...

  4. kgdb接收一个数据包详解

    0    kdb>kgdb  // 可进入kgdb 模式    if (dbg_kdb_mode) {             error = kdb_stub(ks);     } else ...

  5. 利用systemtap定位ifconfig dropped数据包的原因

    http://blog.chinaunix.net/uid-20662820-id-3842431.html   欢迎转载,转载请保留文章的完整性!Author: Tony <tingw.liu ...

  6. 利用jdbc简单封装一个小框架(类似DBUtils)

    利用jdbc写的一个类似DBUtils的框架 package com.jdbc.orm.dbutils; import java.io.IOException; import java.io.Inpu ...

  7. TCP/IP UDP 协议首部及数据进入协议栈封装的过程

    数据的封装 UDP 封装 TCP 封装 IP 封装 检验和算法 当应用程序用TCP传送数据时,数据被传送入协议栈中,然后逐一通过每一层直到被当作一串比特流送入网络 注: UDP数据TCP数据基本一致. ...

  8. 如何抓取基于https协议的webservice数据包

    方法一:基于Fiddler2等第三方工具(需要在Java端禁用SSL安全检查) 原文拷贝自http://blog.csdn.net/zmxj/article/details/6327775,向原作者表 ...

  9. 第8章 传输层(1)_TCP/UDP协议的应用场景

    1. 传输层的两个协议 1.1 TCP和UDP协议的应用场景 (1)TCP协议:如果要传输的内容比较多,需要将发送的内容分成多个数据包发送.这就要求在传输层用TCP协议,在发送方和接收方建立连接,实现 ...

随机推荐

  1. 第五届蓝桥杯校内选拔第六题_(dfs)

    你一定听说过“数独”游戏.如[图1.png],玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个同色九宫内的数字均含1-9,不重复. 数独的答案都是唯一的,所以 ...

  2. HDU_1561_The more, The Better_树型dp

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561 The more, The Better Time Limit: 6000/2000 MS (J ...

  3. 16位/32位/64位CPU的位究竟是说啥

    平时,我们谈论CPU,都会说某程序是32位编译,可以跑在32位机或64位机,或则是在下载某些开源包时,也分32位CPU版本或64CPU位版本,又或者在看计算机组成相关书籍时,特别时谈到X86 CPU时 ...

  4. Manjaro安装配置美化字体模糊发虚解决记录

    Manjaro安装记录 前言: ​ 记录自己Manjaro18安装的一些坑,避免下次满互联网找解决方法.在此之前试过Manjaro.Ubuntu.Fedora.linux Mint系统的pac.yum ...

  5. JavaScript ES6 数组新方法 学习随笔

    JavaScript ES6 数组新方法 学习随笔 新建数组 var arr = [1, 2, 2, 3, 4] includes 方法 includes 查找数组有无该参数 有返回true var ...

  6. Spring Boot之简单的MVC

    最近开始看Spring Boot,发现其开发起来真是方便.今天就来实现一个简单的Spring MVC 请求,纯Java代码的哦. 1.Maven必不可少,先看看都加载了那些依赖: <?xml v ...

  7. Linux 查看发行版版本信息和内核版本

    版本信息: cat  /etc/centos-release  或 redhat-release cat  /etc/issiue 内核信息:uname -r   或   uname  -a

  8. Linux命令学习(3): zcat 直接查看压缩文件

    版权声明:本文为博主原创文章,未经允许不得转载. zcat 用途:在不解压文件的情况下,直接将文件内容输出到标准输出.(原压缩文件不做任何更改) 格式:zcat [-n] [-V] [FILE] 参数 ...

  9. Python爬虫入门教程: 27270图片爬取

    今天继续爬取一个网站,http://www.27270.com/ent/meinvtupian/ 这个网站具备反爬,so我们下载的代码有些地方处理的也不是很到位,大家重点学习思路,有啥建议可以在评论的 ...

  10. 如何通过js在子页面调用父页面元素的click事件

    //获取父页面的某个元素var node = window.parent.document.getElementById("btnReturn");//调用该元素的Click事件 ...