TCP/IP 协议簇的逐层封装

        在使用 TCP 协议的网络程序中,用户数据从产生到从网卡发出去一般要经过如下的逐层封装过程:


        从下往上看:
        1)链路层通过加固定长度的首部、尾部来封装 IP 数据报(Datagram) 产生以太网帧(Frame)。 其中首部存在对封装数据的标识:是 IP(0x0800,例如本例) 、ARP(0x0806) 还是 RARP(0x0835)。
        2)网络层通过加 IP首部来封装 TCP 段(Segment) 产生 IP 数据报。 其中首部存在对封装数据的标识:是 ICMP(0x01)、IGMP(0x02)、TCP(0x06,例如本例)还是 UDP(0x11)。
        3)传输层通过加首部来封装应用数据产生 TCP 段。其中TCP首部存在对封装数据的标识:端口号,来标识是那个应用程序产生的数据。

        4)按这种处理逻辑,在应用层,对于我们要处理的应用数据理所当然的加上固定长度的首部,首部中同样含有某些标识,标识些什么呢?按经验,一般会标识本次数据的业务意义,在程序中一般处理为业务集合(枚举型)的某个元素;如果是 TCP应用(本例) 还可能包括应用数据总体长度。


Ethernet、Tcp、Udp 等协议的数据包格式

        TCP/IP协议是一个比较复杂的协议集,有很多专业书籍介绍。在此,我仅介绍其与编程密切相关的部分:以太网上 TCP/IP 协议的分层结构及其报文格式。我们知道TCP/IP 协议采用分层结构,其分层模型及协议如下表:

        协议采用分层结构,因此,数据报文也采用分层封装的方法。下面以应用最广泛的以太网为例说明其数据报文分层封装,如下图所示:

        任何通讯协议都有独特的报文格式,TCP/IP 协议也不例外。对于通讯协议编程,我们首先要清楚其报文格式。由于TCP/IP 协议采用分层模型,各层都有专用的报头,以下就简单介绍以太网下 TCP/IP 各层报文格式。


        8 字节的前导用于帧同步,CRC 域用于帧校验。这些用户不必关心其由网卡芯片自动添加。目的地址和源地址是指网卡的物理地址,即 MAC 地址,具有唯一性。帧类型或协议类型是指数据包的高级协议,如 0x0806 表示 ARP 协议,0x0800 表示 IP 协议等。之所以要把数据组合成以帧为单位传送,是为了在出错时,可只将有错的帧重发,而不必将全部数据重新发送,从而提高了效率。注:数据以帧为单位进行发送,若某一帧有差错,以后就重传这个出错的帧。一个帧要有帧界限,接收端在收到比特流后,能够依据帧界限正确知道哪些比特构成一个帧。接收端找到帧定界符并确定帧的准确位置,就是完成了帧同步。

          硬件类型:指明了发送方想知道的硬件接口类型,以太网的值为1;
          协议类型:指明了发送方提供的高层协议类型,IP为0800(16进制);
          硬件地址长度和协议长度:指明了硬件地址和高层协议地址的长度,这样ARP报文就可以在任意硬件和任意协议的网络中使用;
          操作类型:用来表示这个报文的类型,ARP请求为1,ARP响应为2,RARP请求为3,RARP响应为4;
          发送方硬件地址(0-3字节):源主机硬件地址的前3个字节;
          发送方硬件地址(4-5字节):源主机硬件地址的后3个字节;
          发送方IP地址(0-1字节):源主机硬件地址的前2个字节;
          发送方IP地址(2-3字节):源主机硬件地址的后2个字节;
          目标硬件地址(0-1字节):目的主机硬件地址的前2个字节;
          目标硬件地址(2-5字节):目的主机硬件地址的后4个字节;
         目标IP地址(0-3字节):目的主机的IP地址。


        IP 数据报头格式如下图:


       版本号(Version)长度4比特。标识目前采用的IP协议的版本号。一般的值为0100(IPv4),0110(IPv6)
        IP包头长度(Header Length)长度4比特。描述IP包头的长度。因为在IP包头中有变长的可选部分。该部分占4个bit位,单位为32bit(4个字节),即本区域值= IP头部长度(单位为bit)/(8*4),因此,一个IP包头的长度最长为“1111”,即15*4=60个字节。IP包头最小长度为20字节。

        服务类型(Type of Service)长度8比特。这八位被分成如下定义,其中PPP三位组合使用:PPP DTRC0
              PPP:定义包的优先级,取值越大数据越重要
                  000 普通 (Routine)
                  001 优先的 (Priority)
                  010 立即的发送 (Immediate)
                  011 闪电式的 (Flash)
                  100 比闪电还闪电式的 (Flash Override)
                  101 CRI/TIC/ECP(找不到这个词的翻译)
                  110 网间控制 (Internetwork Control)
                  111 网络控制 (Network Control)

                   D 时延: 0:普通 1:延迟尽量小
                  T 吞吐量: 0:普通 1:流量尽量大
                  R 可靠性: 0:普通 1:可靠性尽量大
                  M 传输成本: 0:普通 1:成本尽量小
                  0 最后一位被保留,恒定为0

       IP包总长(Total Length)长度16比特。 以字节为单位计算的IP包的长度 (包括头部和数据),所以IP包最大长度65535字节。
        标识符(Identifier):长度16比特。该字段和Flags和Fragment Offest字段联合使用,对较大的上层数据包进行分段(fragment)操作。路由器将一个包拆分后,所有拆分开的小包被标记相同的值,以便目的端设备能够区分哪个包属于被拆分开的包的一部分。
        标记(Flags)长度3比特。该字段第一位不使用。第二位是DF(Don't Fragment)位,DF位设为1时表明路由器不能对该上层数据包分段。如果一个上层数据包无法在不分段的情况下进行转发,则路由器会丢弃该上层数据包并返回一个错误信息。第三位是MF(More Fragments)位,当路由器对一个上层数据包分段,则路由器会在除了最后一个分段的IP包的包头中将MF位设为1。
        片偏移(Fragment Offset)长度13比特。表示该IP包在该组分片包中位置,接收端靠此来组装还原IP包。
        生存时间(TTL)长度8比特。当IP包进行传送时,先会对该字段赋予某个特定的值。当IP包经过每一个沿途的路由器的时候,每个沿途的路由器会将IP包的TTL值减少1。如果TTL减少为0,则该IP包会被丢弃。这个字段可以防止由于路由环路而导致IP包在网络中不停被转发。

        协议(Protocol)长度8比特。标识了上层所使用的协议。
                以下是比较常用的协议号:
                          1    ICMP
                          2    IGMP
                          6    TCP
                          17    UDP
                          88    IGRP
                          89    OSPF
      头部校验(Header Checksum)长度16位。用来做IP头部的正确性检测,但不包含数据部分。 因为每个路由器要改变TTL的值,所以路由器会为每个通过的数据包重新计算这个值。
       起源和目标地址(Source and Destination Addresses)这两个地段都是32比特。标识了这个IP包的起源和目标地址。要注意除非使用NAT,否则整个传输的过程中,这两个地址不会改变。
       至此,IP包头基本的20字节已介绍完毕,此后部分属于可选项,不是必须的部分。

      可选项(Options):这是一个可变长的字段。该字段属于可选项,主要用于测试,由起源设备根据需要改写。可选项目包含以下内容:
      松散源路由(Loose source routing):给出一连串路由器接口的IP地址。IP包必须沿着这些IP地址传送,但是允许在相继的两个IP地址之间跳过多个路由器。
      严格源路由(Strict source routing):给出一连串路由器接口的IP地址。IP包必须沿着这些IP地址传送,如果下一跳不在IP地址表中则表示发生错误。
      路由记录(Record route):当IP包离开每个路由器的时候记录路由器的出站接口的IP地址。
      时间戳(Timestamps):当IP包离开每个路由器的时候记录时间。
      填充(Padding):因为IP包头长度(Header Length)部分的单位为32bit,所以IP包头的长度必须为32bit的整数倍。因此,在可选项后面,IP协议会填充若干个0,以达到32bit的整数倍。

typedef struct _iphdr //定义IP首部  
{  
unsigned char h_lenver; //4位首部长度+4位IP版本号  
unsigned char tos; //8位服务类型TOS  
unsigned short total_len; //16位总长度(字节)
unsigned short ident; //16位标识  
unsigned short frag_and_flags; //3位标志位  
unsigned char ttl; //8位生存时间 TTL  
unsigned char proto; //8位协议 (TCP, UDP 或其他)  
unsigned short checksum; //16位IP首部校验和 
unsigned int sourceIP; //32位源IP地址  
unsigned int destIP; //32位目的IP地址  
}IP_HEADER;

        我们用单片机实现 TCP/IP 协议要作一些简化,不考虑数据分片和优先权。因此,在此我们不讨论服务类型和标志偏移域,只需填“0” 即可。协议“版本”为 4,“头长度”单位为 32Bit,“总长度”以字节为单位,表示整个 IP 数据报长度。“标识”是数据包的 ID 号,用于识别不同的 IP 数据包。“生存时间” TTL 是个数量及的概念,防止无用数据包一直存在网络中。一般每经过路由器时减一,因此通过 TTL 可以算出数据包到达目的地所经过的路由器个数。“协议”域表示创建该数据包的高级协议类型。如 1 表示 ICMP 协议,6 表示 TCP 协议,17 表示 UDP 协议等。IP 数据包为简化数据转发时间,仅采用头校验的方法,数据正确性由高层协议保证。


        ICMP(网间网控制报文协议)协议      应用广泛。在此仅给出最常见的回应请求与应答报文格式, 用户命令 ping 便是利用此报文来测试信宿机的可到达性。 报文格式如下图所示:

       类型 0 为回应应答报文,8 为回应请求报文。整个数据包均参与检验。注意 ICMP 封装在 IP 数据包里传送。

        TCP 是面向连接的可靠数据传输协议,因此比较复杂,在此仅作简单介绍。“序号”指数据在发送端数据流中的位置。“确认号”指出本机希望下一个接收的字节的序号。与 IP 校验不同的是 TCP,UDP 校验采用伪头标加整个报文一同校验的方法。TCP 协议工作原理另行介绍。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/255139.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【开源程序(C++)】获取bing图片并自动设置为电脑桌面背景

众所周知,bing搜索网站首页每日会更新一张图片,张张漂亮(额,也有一些不合我口味的),特别适合用来做电脑壁纸。 我们想要将bing网站背景图片设置为电脑桌面背景的通常做法是: 上网,搜…

UIProgressView 圆角

里面外面都变成圆角 不用图片 直接改变layer 重点是里面外面都是圆角哦 for (UIImageView * imageview in self.progress.subviews) { imageview.layer.cornerRadius 5; imageview.clipsToBounds YES; } 转载于:https://www.cnblogs.com/huoran1120/p/5563991.html

HALCON示例程序holes.hdev孔洞提取

HALCON示例程序holes.hdev孔洞提取 示例程序源码(加注释) 关于显示类函数解释 read_image (Image, ‘progres’) get_image_size (Image, Width, Height) dev_close_window () dev_open_window (0, 0, Width, Height, ‘white’, WindowID) dev_set_co…

给实例动态增加方法VS给类动态增加方法

一、给实例绑定方法 object.method MethodType(method,object) >>>class Badbrains(): pass >>>def mocking(self): print(Brain\s Mocking) >>>b Badbrains() >>>from types import MethodType >>>b.mocking MethodType(moc…

一句DOS命令搞定文件合并

用Dos的copy命令实现: copy a.jsb.jsc.js abc.js /b 将 a.js b.js c.js 合并为一个 abc.js,最后的 /b 表示文件为二进位文件,copy 命令的其它参数可以在 cmd 里输入 copy /? 学习 举例:如果想要合并多个js文件到某个目录下&#…

DataTables warning: Requested unknown parameter '0' from the data source for row '0'

问题&#xff1a;DataTables warning: Requested unknown parameter 0 from the data source for row 0 代码&#xff1a; <script type"text/javascript">var data [{"Name":"UpdateBootProfile","Result":"PASS",&…

HALCON示例程序hull.hdev区域提取与凸度筛选

HALCON示例程序hull.hdev区域提取与凸度筛选 示例程序源码&#xff08;加注释&#xff09; 关于显示类函数解释 read_image (Hull, ‘hull’) get_image_size (Hull, Width, Height) dev_close_window () dev_open_window (0, 0, Width, Height, ‘black’, WindowID) dev_di…

我与Linux系统的交集

2019独角兽企业重金招聘Python工程师标准>>> 一、初识Linux 第一次知道Linux还是在我刚进大学的时候&#xff0c;从开始聊QQ、玩斗地主的时候起我就是用的Windows&#xff0c;从Windows2000一直到Windows7&#xff0c;当时我已经完全习惯了使用Windows&#xff0c;而…

squid白名单

http_access deny all #取消注释 http_access allow all --> http_access allow xxx_custom_ip#添加系统服务器IP白名单 acl xdaili_custom_ip src 60.191.4.xxx/32 acl xdaili_custom_ip src 139.196.210.xxx/32 acl xdaili_custom_ip src 139.196.172.xxx/32 acl xdail…

HALCON示例程序IC.hdev通过电路板元器件定位识别

HALCON示例程序IC.hdev通过电路板元器件定位识别 示例程序源码&#xff08;加注释&#xff09; 关于显示类函数解释 dev_close_window () read_image (Image, ‘ic’) get_image_size (Image, Width, Height) dev_open_window (0, 0, Width, Height, ‘black’, WindowID) de…

IP头、TCP头、UDP头详解以及定义

一、MAC帧头定义 /*数据帧定义&#xff0c;头14个字节&#xff0c;尾4个字节*/ typedef struct _MAC_FRAME_HEADER { char m_cDstMacAddress[6]; //目的mac地址 char m_cSrcMacAddress[6]; //源mac地址 short m_cType;      //上一层协议类型&#xff0c;如…

关于iOS 3D touch 指纹验证的随笔

file:///Users/OWen/Desktop/3DTouch.png 随着iOS系统不断的更新迭代&#xff0c;苹果总会推出一些新的功能&#xff0c;今天就研究了一下iOS8之后推出的指纹验证的功能&#xff0c;然后写了一个小demo&#xff0c;与君分享。。 上demo&#xff1a; 1&#xff1a;首先导入一个…

HALCON示例程序inner_rectangle1.hdev木板有效区域提取

HALCON示例程序inner_rectangle1.hdev木板有效区域提取 示例程序源码&#xff08;加注释&#xff09; 关于显示类函数解释 dev_update_window (‘off’) dev_update_var (‘off’) dev_update_pc (‘off’) read_image (Image, ‘wood_knots’) get_image_size (Image, Width…

vsCode ext install 不工作

vsCode 扩展商店 不可用 ext 不可用 ext install eamodio.gitlens 1、搜索离线插件https://marketplace.visualstudio.com/vscode 2、插件离线插件模板https://marketplace.gallery.vsassets.io/_apis/public/gallery/publisher/marketplace/extension/${extension name}/${ver…

递归实现 十进制转换其他进制(2-16)

1 def to_str(n, base): 2 convert_string "0123456789ABCDEF" 3 if n < base: 4 return convert_string[n] 5 else: 6 return to_str(n / base, base) convert_string[n % base] 7 8 print to_str(168, 8) 转载于:https://www.cn…

在UltraEdit的查找和替换中使用正则表达式 (转)

很多朋友都用过或者正在用UltraEdit&#xff0c;这个编辑器陪伴我也好几年了&#xff0c;从很多地方影响着我写代码的快捷键习惯&#xff0c;Ultraedit提供了非常丰富的编辑功能&#xff0c;其中非常重要的查找和替换功能一定大家都用过&#xff0c;Ultraedit提供的查找替换功能…

基本 TCP 套接字编程讲解

基于 TCP 的套接字编程的所有客户端和服务器端都是从调用socket 开始&#xff0c;它返回一个套接字描述符。客户端随后调用connect 函数&#xff0c;服务器端则调用 bind、listen 和accept 函数。 使用套接口客户机服务器的的例子 sever.c #include <stdio.h> #include &…

HALCON示例程序inspect_bga.hdev测量bga焊点缺陷

HALCON示例程序inspect_bga.hdev测量bga焊点缺陷 示例程序源码&#xff08;加注释&#xff09; 关于显示类函数解释 read_image (Image, ‘bga_14x14_model’) get_image_pointer1 (Image, Pointer, Type, Width, Height) dev_update_off () dev_close_window () dev_open_win…

怎样屏蔽微信朋友圈视频?局域网如何禁止员工看朋友圈视频?

上班时间刷刷朋友圈&#xff0c;一眨眼半小时就过去了。不但会影响工作效率&#xff0c;而且朋友圈的视频会占用大量的带宽。所以对企业管理人员来说&#xff0c;很多时候需要禁止员工在工作时段刷朋友圈。但是行政手段要和技术手段配合&#xff0c;才可以发挥真正的作用。本文…

cf414B(dp)

题目链接&#xff1a;http://codeforces.com/problemset/problem/414/B 题意&#xff1a;定义所有元素是其前一个元素的倍数的数列为good sequence&#xff0c;给出 n, 和 k&#xff0c;求1....n组成的长度为k的good sequence 的数目&#xff1b; 思路&#xff1a;dp 用dp[i][j…