Linux网络编程(四)-协议02:协议格式(数据包封装格式)【①应用层:HTTP、FTP、RPC;②传输层:TCP、UDP;③网络层:IP;④链路层:ARP(通过广播找ip对应的mac)】
一、应用层-协议
1、HTTP(超文本传输协议)
2、FTP(文件传输协议)
3、各类RPC协议
二、传输层-协议
1、UDP(用户数据报协议)【数据传输不可靠】
UDP是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。没有确认机制,丢包不重传。局域网内通信一般用UDP协议。
1.1、UDP报头【UDP报头大小:8字节】
![](https://img-blog.csdnimg.cn/4a2a7a1c1c994b75acba85cd28858b2e.png)
- 源端口号:发送方端口号
- 目的端口号:接收方端口号
- 长度:UDP用户数据报的长度,最小值是8字节(仅有首部),总长度为UDP首部长度(8字节)+数据主体长度;
- 校验和:检测UDP用户数据报在传输中是否有错,有错就丢弃。校验有各种方法,简单地,可以将传输的数据按照每4个字节组成一个int数,将所有int数加起来,接收方和发送方可以校验该数据在发送方与接收方是否一致,来判断数据是否有丢包;
1.2、UDP分析
下面分析一帧基于UDP的TFTP协议帧。
以太网首部
0000: 00 05 5d 67 d0 b1 00 05 5d 61 58 a8 08 00
IP首部
0000: 45 00
0010: 00 53 93 25 00 00 80 11 25 ec c0 a8 00 37 c0 a8
0020: 00 01
UDP首部
0020: 05 d4 00 45 00 3f ac 40
TFTP协议
0020: 00 01 'c'':''\''q'
0030: 'w''e''r''q''.''q''w''e'00 'n''e''t''a''s''c''i'
0040: 'i'00 'b''l''k''s''i''z''e'00 '5''1''2'00 't''i'
0050: 'm''e''o''u''t'00 '1''0'00 't''s''i''z''e'00 '0'
0060: 00以太网首部:源MAC地址是00:05:5d:61:58:a8,目的MAC地址是00:05:5d:67:d0:b1,上层协议类型0x0800表示IP。
IP首部:每一个字节0x45包含4位版本号和4位首部长度,版本号为4,即IPv4,首部长度为5,说明IP首部不带有选项字段。服务类型为0,没有使用服务。16位总长度字段(包括IP首部和IP层payload的长度)为0x0053,即83字节,加上以太网首部14字节可知整个帧长度是97字节。IP报标识是0x9325,标志字段和片偏移字段设置为0x0000,就是DF=0允许分片,MF=0此数据报没有更多分片,没有分片偏移。TTL是0x80,也就是128。上层协议0x11表示UDP协议。IP首部校验和为0x25ec,源主机IP是c0 a8 00 37(192.168.0.55),目的主机IP是c0 a8 00 01(192.168.0.1)。
UDP首部:源端口号0x05d4(1492)是客户端的端口号,目的端口号0x0045(69)是TFTP服务的well-known端口号。UDP报长度为0x003f,即63字节,包括UDP首部和UDP层pay-load的长度。UDP首部和UDP层payload的校验和为0xac40。
TFTP是基于文本的协议,各字段之间用字节0分隔,开头的00 01表示请求读取一个文件,接下来的各字段是:
c:\qwerq.qwe
netascii
blksize 512
timeout 10
tsize 0
一般的网络通信都是像TFTP协议这样,通信的双方分别是客户端和服务器,客户端主动发起请求(上面的例子就是客户端发起的请求帧),而服务器被动地等待、接收和应答请求。客户端的IP地址和端口号唯一标识了该主机上的TFTP客户端进程,服务器的IP地址和端口号唯一标识了该主机上的TFTP服务进程,由于客户端是主动发起请求的一方,它必须知道服务器的IP地址和TFTP服务进程的端口号,所以,一些常见的网络协议有默认的服务器端口,例如HTTP服务默认TCP协议的80端口,FTP服务默认TCP协议的21端口,TFTP服务默认UDP协议的69端口(如上例所示)。在使用客户端程序时,必须指定服务器的主机名或IP地址,如果不明确指定端口号则采用默认端口,请读者查阅ftp、tftp等程序的man page了解如何指定端口号。/etc/services中列出了所有well-known的服务端口和对应的传输层协议,这是由IANA(Internet Assigned Numbers Authority)规定的,其中有些服务既可以用TCP也可以用UDP,为了清晰,IANA规定这样的服务采用相同的TCP或UDP默认端口号,而另外一些TCP和UDP的相同端口号却对应不同的服务。
很多服务有well-known的端口号,然而客户端程序的端口号却不必是well-known的,往往是每次运行客户端程序时由系统自动分配一个空闲的端口号,用完就释放掉,称为ephemeral的端口号,想想这是为什么?
前面提过,UDP协议不面向连接,也不保证传输的可靠性,例如:
发送端的UDP协议层只管把应用层传来的数据封装成段交给IP协议层就算完成任务了,如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息。
接收端的UDP协议层只管把收到的数据根据端口号交给相应的应用程序就算完成任务了,如果发送端发来多个数据包并且在网络上经过不同的路由,到达接收端时顺序已经错乱了,UDP协议层也不保证按发送时的顺序交给应用层。
通常接收端的UDP协议层将收到的数据放在一个固定大小的缓冲区中等待应用程序来提取和处理,如果应用程序提取和处理的速度很慢,而发送端发送的速度很快,就会丢失数据包,UDP协议层并不报告这种错误。
因此,使用UDP协议的应用程序必须考虑到这些可能的问题并实现适当的解决方案,例如等待应答、超时重发、为数据包编号、流量控制等。
一般使用UDP协议的应用程序实现都比较简单,只是发送一些对可靠性要求不高的消息,而不发送大量的数据。例如:
- 基于UDP的TFTP协议一般只用于传送小文件(所以才叫trivial的ftp)
- 基于TCP的FTP协议适用于各种文件的传输
TCP协议又是如何用面向连接的服务来代替应用程序解决传输的可靠性问题呢。
2、TCP(传输控制协议)
TCP:一种面向连接的、可靠的、基于字节流的传输层通信协议。
一般跨网关传输用TCP,有确认机制,比较安全,丢包重传。
因为有确认机制,所以效率不如UDP。
2.1、TCP报头【TCP报头大小:20字节】
![](https://img-blog.csdnimg.cn/71bd58f007d8433491be23f4d9f35789.png)
与UDP协议一样也有源端口号和目的端口号,通讯的双方由IP地址和端口号标识。32位序号、32位确认序号、窗口大小稍后详细解释。4位首部长度和IP协议头类似,表示TCP协议头的长度,以4字节为单位,因此TCP协议头最长可以是4x15=60字节,如果没有选项字段,TCP协议头最短20字节。URG、ACK、PSH、RST、SYN、FIN是六个控制位,本节稍后将解释SYN、ACK、FIN、RST四个位,其它位的解释从略。16位检验和将TCP协议头和数据都计算在内。紧急指针和各种选项的解释从略。
- 源端口号:发送方端口号
- 目的端口号:接收方端口号
- 序列号:本报文段的数据的第一个字节的序号
- 确认序号:期望收到对方下一个报文段的第一个数据字节的序号
- 头部长度(数据偏移):TCP报文段的数据起始处距离TCP报文段的起始处有多远,即首部长度。单位:32位,即以4字节为计算单位。即:如果此处填写5,则头部长度为 5×4=20字节;
- 保留:占6位,保留为今后使用,目前应置为0
- 紧急URG: 此位置1,表明紧急指针字段有效,它告诉系统此报文段中有紧急数据,应尽快传送
- 确认ACK: 仅当ACK=1时确认号字段才有效,TCP规定,在连接建立后所有传达的报文段都必须把ACK置1
- 推送PSH:当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP就可以使用推送(push)操作,这时,发送方TCP把PSH置1,并立即创建一个报文段发送出去,接收方收到PSH=1的报文段,就尽快地(即“推送”向前)交付给接收应用进程,而不再等到整个缓存都填满后再向上交付
- 复位RST: 用于复位相应的TCP连接
- 同步SYN: 仅在三次握手建立TCP连接时有效。当SYN=1而ACK=0时,表明这是一个连接请求报文段,对方若同意建立连接,则应在相应的报文段中使用SYN=1和ACK=1.因此,SYN置1就表示这是一个连接请求或连接接受报文
- 终止FIN:用来释放一个连接。当FIN=1时,表明此报文段的发送方的数据已经发送完毕,并要求释放运输连接。
- 窗口尺寸:指发送本报文段的一方的接收窗口(而不是自己的发送窗口),接收方用于接收数据的缓冲区的剩余大小;
- 校验和:校验和字段检验的范围包括首部和数据两部分,在计算校验和时需要加上12字节的伪头部
- 紧急指针:仅在URG=1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据),即指出了紧急数据的末尾在报文中的位置,注意:即使窗口为零时也可发送紧急数据。一般写0
- 选项:长度可变,最长可达40字节,当没有使用选项时,TCP首部长度是20字节
三、网络层-协议
1、IP协议(因特网互联协议)
1.1、IP报头【IP报头大小:20字节】
IP数据报的首部长度和数据长度都是可变长的,但总是4字节的整数倍。对于IPv4,4位版本字段是4。4位首部长度的数值是以4字节为单位的,最小值为5,也就是说首部长度最小是4x5=20字节,也就是不带任何选项的IP首部,4位能表示的最大值是15,也就是说首部长度最大是60字节。8位TOS字段有3个位用来指定IP数据报的优先级(目前已经废弃不用),还有4个位表示可选的服务类型(最小延迟、最大?吐量、最大可靠性、最小成本),还有一个位总是0。总长度是整个数据报(包括IP首部和IP层payload)的字节数。每传一个IP数据报,16位的标识加1,可用于分片和重新组装数据报。3位标志和13位片偏移用于分片。TTL(Time to live)是这样用的:源主机为数据包设定一个生存时间,比如64,每过一个路由器就把该值减1,如果减到0就表示路由已经太长了仍然找不到目的主机的网络,就丢弃该包,因此这个生存时间的单位不是秒,而是跳(hop)。协议字段指示上层协议是TCP、UDP、ICMP还是IGMP。然后是校验和,只校验IP首部,数据的校验由更高层协议负责。IPv4的IP地址长度为32位。
想一想,前面讲了以太网帧中的最小数据长度为46字节,不足46字节的要用填充字节补上,那么如何界定这46字节里前多少个字节是IP、ARP或RARP数据报而后面是填充字节?
- 版本:IP协议的版本。通信双方使用过的IP协议的版本必须一致,目前最广泛使用的IP协议版本号为4(即IPv4 )
- 首部长度:单位是32位(4字节)
- 服务类型:一般不适用,取值为0
- 总长度:指首部加上数据的总长度,单位为字节
- 标识(identification):IP软件在存储器中维持一个计数器,每产生一个数据报,计数器就加1,并将此值赋给标识字段
- 标志(flag):目前只有两位有意义。
- 标志字段中的最低位记为MF。MF=1即表示后面“还有分片”的数据报。MF=0表示这已是若干数据报片中的最后一个。
- 标志字段中间的一位记为DF,意思是“不能分片”,只有当DF=0时才允许分片
- 片偏移:指出较长的分组在分片后,某片在源分组中的相对位置,也就是说,相对于用户数据段的起点,该片从何处开始。片偏移以8字节为偏移单位。
- 生存时间:TTL,表明是数据报在网络中的寿命,即为“跳数限制”,由发出数据报的源点设置这个字段。路由器在转发数据之前就把TTL值减一,当TTL值减为零时,就丢弃这个数据报。
- 协议类型:指出此数据报携带的数据时使用何种协议,以便使目的主机的IP层知道应将数据部分上交给哪个处理过程,常用的:
- ICMP:填1;
- IGMP:填2;
- TCP:填6;
- UDP:填17;
- IPv6:填41;
- 头部校验和:只校验数据报的首部,不包括数据部分。
- 源地址:发送方IP地址
- 目的地址:接收方IP地址
四、链路层
1、以太网(Mac)帧格式
以太网(Mac)的帧格式【MAC报头大小:14字节】如下所示:
其中:
- 源地址、目的地址是指网卡的硬件地址(也叫MAC地址),长度是48位(6字节),是在网卡出厂时固化的。可在shell中使用ifconfig命令查看,“HWaddr 00:15:F2:14:9E:3F”部分就是硬件地址。
- 类型:协议类型字段有三种值,分别对应:
- IP:0800,表示数据包为IP数据包;;
- ARP:0806,表示数据包为ARP数据包;;
- RARP:8035,表示数据包为RARP数据包;;
- CRC:帧尾是CRC校验码。
- 数据:以太网帧中的数据长度规定最小46字节,最大1500字节。
- ARP和RARP数据包的长度不够46字节,要在后面补填充位。
- 最大值1500称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU,如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的MTU,则需要对数据包进行分片(fragmentation)。
- ifconfig命令输出中也有“MTU:1500”。
- 注意:MTU这个概念指数据帧中有效载荷的最大长度,不包括帧头长度。
2、ARP协议【ARP报头大小:14字节】【属于Mac协议的一种】
在网络通讯时,源主机的应用程序知道目的主机的IP地址和端口号,却不知道目的主机的硬件地址(Mac地址),而数据包在目的主机(数据接收方)首先是被网卡接收到再去处理上层协议的,如果接收到的数据包的硬件地址与本机不符,则直接丢弃。
因此在通讯前必须获得“目的主机”的硬件地址。ARP协议就起到这个作用。
- 源主机发出ARP请求,询问“IP地址是192.168.0.1的主机的硬件地址(Mac地址)是多少”,并将这个请求广播到本地网段(以太网帧首部的硬件地址填FF:FF:FF:FF:FF:FF表示广播),目的主机接收到广播的ARP请求,发现其中的IP地址与本机相符,则发送一个ARP应答数据包给源主机,将自己的硬件地址填写在应答包中。
- 如果本地网段没有找到IP地址,则直接将该ARP请求发送给本地网关,让网关去外部网段去找该IP对应的Mac地址。
每台主机都维护一个ARP缓存表,可以用 arp -a 命令查看。
缓存表中的表项有过期时间(一般为20分钟),如果20分钟内没有再次使用某个表项,则该表项失效,下次还要发ARP请求来获得目的主机的硬件地址。
想一想,为什么表项要有过期时间而不是一直有效?
2.1、ARP报头【ARP报头大小:14字节】
- 源MAC地址、目的MAC地址在以太网首部和ARP请求中各出现一次,对于链路层为以太网的情况是多余的,但如果链路层是其它类型的网络则有可能是必要的。
硬件类型指链路层网络类型,1为以太网,协议类型指要转换的地址类型,0x0800为IP地址,后面两个地址长度对于以太网地址和IP地址分别为6和4(字节),op字段为1表示ARP请求,op字段为2表示ARP应答。
- Dest MAC:目的MAC地址
- Src MAC:源MAC地址
- 帧类型:0x0806
- 硬件类型:1(以太网)
- 协议类型:0x0800(IP地址)
- 硬件地址长度:6
- 协议地址长度:4
- OP:
- (ARP请求),
- 2(ARP应答),
- 3(RARP请求),
- 4(RARP应答)
2.2、ARP请求在网络中的流向
2.3、ARP组包
看一个具体的例子。
任何网关如果获得Dest Mac为ff:ff:ff:ff:ff:ff的ARP请求,说明是广播,必须无条件接收。(一般出不了局域网)
请求帧如下(为了清晰在每行的前面加了字节计数,每行16个字节):
以太网首部(14字节)
0000: ff ff ff ff ff ff 00 05 5d 61 58 a8 08 06
ARP帧(28字节)
0000: 00 01
0010: 08 00 06 04 00 01 00 05 5d 61 58 a8 c0 a8 00 37
0020: 00 00 00 00 00 00 c0 a8 00 02
填充位(18字节)
0020: 00 77 31 d2 50 10
0030: fd 78 41 d3 00 00 00 00 00 00 00 00
以太网首部:目的主机采用广播地址,源主机的MAC地址是00:05:5d:61:58:a8,上层协议类型0x0806表示ARP。
ARP帧:硬件类型0x0001表示以太网,协议类型0x0800表示IP协议,硬件地址(MAC地址)长度为6,协议地址(IP地址)长度为4,op为0x0001表示请求目的主机的MAC地址,源主机MAC地址为00:05:5d:61:58:a8,源主机IP地址为c0 a8 00 37(192.168.0.55),目的主机MAC地址全0待填写,目的主机IP地址为c0 a8 00 02(192.168.0.2)。
由于以太网规定最小数据长度为46字节,ARP帧长度只有28字节,因此有18字节填充位,填充位的内容没有定义,与具体实现相关。
应答帧如下:
以太网首部
0000: 00 05 5d 61 58 a8 00 05 5d a1 b8 40 08 06
ARP帧
0000: 00 01
0010: 08 00 06 04 00 02 00 05 5d a1 b8 40 c0 a8 00 02
0020: 00 05 5d 61 58 a8 c0 a8 00 37
填充位
0020: 00 77 31 d2 50 10
0030: fd 78 41 d3 00 00 00 00 00 00 00 00
以太网首部:目的主机的MAC地址是00:05:5d:61:58:a8,源主机的MAC地址是00:05:5d:a1:b8:40,上层协议类型0x0806表示ARP。
ARP帧:硬件类型0x0001表示以太网,协议类型0x0800表示IP协议,硬件地址(MAC地址)长度为6,协议地址(IP地址)长度为4,op为0x0002表示应答,源主机MAC地址为00:05:5d:a1:b8:40,源主机IP地址为c0 a8 00 02(192.168.0.2),目的主机MAC地址为00:05:5d:61:58:a8,目的主机IP地址为c0 a8 00 37(192.168.0.55)。
思考题:如果源主机和目的主机不在同一网段,ARP请求的广播帧无法穿过路由器,源主机如何与目的主机通信?
相关文章
- SLAM学习笔记三-----第五章的实现及opencv的linux下的编译方法
- Linux网络编程(六)-高并发服务器03-I/O多路复用03:epoll反应堆【对epoll的封装】【epoll使用C++封装回调函数】
- 在 Linux 中自动生成 Cordova/Phonegap for Android 的 APK 安装程序
- linux系统最小化安装后的初始化脚本
- [读书笔记]Linux命令行与shell编程读书笔记02 环境变量以及其他
- linux命令学习之:vim
- Linux下查看文件和文件夹大小
- 【Linux】apt-get install 怎么阻止弹出框,使用脚本默认自动安装?
- Linux 文件基本属性
- linux 利用 crontab 实现 程序开机启动/crontab任务的多种实现方法
- Linux系统调用过程
- Linux c 目录操作函数scandir