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

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",&…

我与Linux系统的交集

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

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;如…

基本 TCP 套接字编程讲解

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

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

上班时间刷刷朋友圈&#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…

增量值编码器、单圈绝对值编码器、多圈绝对值编码器

主流的伺服电机位置反馈元件包括增量值编码器&#xff0c;单圈绝对值编码器&#xff0c;多圈绝对值编码器&#xff0c;旋转变压器等。下面分别介绍&#xff1a; 增量值编码器增量式编码器是将位移转换成周期性的电信号&#xff0c;再把这个电信号转变成计数脉冲&#xff0c;用…

永磁交流伺服电机的工作原理与更换新编码器后的常规零位校正方法

http://wuhuotun.blog.163.com/blog/static/73085450200910655748516/ 永磁交流伺服电机的编码器相位为何要与转子磁极相位对齐 其唯一目的就是要达成矢量控制的目标&#xff0c;使d轴励磁分量和q轴出力分量解耦&#xff0c;令永磁交流伺服电机定子绕组产生的电磁场始终正交于…

理解Java中字符流与字节流的区别

1. 什么是流 Java中的流是对字节序列的抽象&#xff0c;我们可以想象有一个水管&#xff0c;只不过现在流动在水管中的不再是水&#xff0c;而是字节序列。和水流一样&#xff0c;Java中的流也具有一个“流动的方向”&#xff0c;通常可以从中读入一个字节序列的对象被称为输入…

2018/03/25

2019独角兽企业重金招聘Python工程师标准>>> March 25 2018 Sunday Weather&#xff1a;cloudy 1、需求&#xff1a; a0.5 b3 ca*b 求c的值&#xff1a; [rootDasoncheng sbin]# cat a.sh #!/bin/bash a0.5 b3 cecho $a*$b |bc echo $canswer referred&#xff1a;…

elasticsearch分词聚合查询demo

2019独角兽企业重金招聘Python工程师标准>>> 我们在通过elasticsearch查询text类型的字段时&#xff0c;我们使用aggs进行聚合某个text类型field。这时elasticsearch会自动进行分词将分词后的结果进行聚合。获取每一个分词出现在文档的文档个数。注意&#xff1a;是…

Spring实战第七章

一、SpringMVC配置代替方案 1自定DispatcherServlet 按照AbstractAnnotationConfigDispatcherServletInitializer的定义&#xff0c;它会创建DispatcherServlet和ContextLoaderListener。 AbstractAnnotationConfigDispatcherServletInitializer有三个方法是必须要重载的abstra…

C++多线程(一)

C多线程&#xff08;一&#xff09; WIN 多线程API一 简单实例比较简单的代码&#xff0c;创建10个线程&#xff0c;其中使第4个线程在一创建就挂起&#xff0c;等到其他的线程执行的差不多的时候再使第4个线程恢复执行。#include <stdio.h>#include <stdlib.h>#i…

天梯赛2016-L2

L2-001. 紧急救援 作为一个城市的应急救援队伍的负责人&#xff0c;你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候&#xff0c;你…

伺服系统控制网络的重要性! 现场总线的重要性! SSCNET运动控制系统与发展趋势

引言&#xff1a;在2010年的时候&#xff0c;在北京的一个数控公司工作。产品采用的是通过运动控制卡发脉冲的方式&#xff0c;控制机床的X、Y、Z轴进行加工。 机床在加工产品的时候&#xff0c;一直存在着精度的问题&#xff0c;例如DMG的机床可以达到0.01的加工精度&#x…

EPSON 自带CCD图像处理包使用举例

EPSON 机器人可以购买CCD图像处理包选项&#xff0c;CCD图像处理包与SPEL语言高度结合&#xff0c;可以非常快的将项目投入应用&#xff0c;举例说明CCD图像处理包与SPEL的联合使用。 EPSON 以视觉序列定义图像处理的一个项目&#xff0c;视觉序列是一组按照特定顺序排列的视觉…

索引使用原则

前两篇文章我总结了一些SQL数据库索引的问题&#xff0c;这篇主要来分析下索引的优缼点&#xff0c;以及如何正确使用索引。 索引的优点&#xff1a;这个显而易见&#xff0c;正确的索引会大大提高数据查询&#xff0c;对结果进行排序、分组的操作效率。 索引的缺点…

挂马方式研究、挂马检测技术研究

1. 挂马定义 所谓的挂马&#xff0c;就是黑客通过各种手段&#xff0c;包括SQL注入&#xff0c;网站敏感文件扫描&#xff0c;服务器漏洞&#xff0c;网站程序0day, 等各种方法获得网站管理员账号&#xff0c;然后登陆网站后台&#xff0c;通过数据库"备份/恢复"或者…