网络协议包格式
ARP协议
当主机A要与主机B通信时,地址解析协议可以将主机B的IP地址(192.168.1.2)解析成主机B的MAC地址,以下为工作流程:
第1步:根据主机A上的路由表内容,IP确定用于访问主机B的转发IP地址是192.168.1.2。然后A主机在自己的本地ARP缓存中检查主机B的匹配MAC地址。
第2步:如果主机A在ARP缓存中没有找到映射,它将询问192.168.1.2的硬件地址,从而将ARP请求帧广播到本地网络上的所有主机。源主机A的IP地址和MAC地址都包括在ARP请求中。本地网络上的每台主机都接收到ARP请求并且检查是否与自己的IP地址匹配。如果主机发现请求的IP地址与自己的IP地址不匹配,它将丢弃ARP请求。
第3步:主机B确定ARP请求中的IP地址与自己的IP地址匹配,则将主机A的IP地址和MAC地址映射添加到本地ARP缓存中。
第4步:主机B将包含其MAC地址的ARP回复消息直接发送回主机A。
第5步:当主机A收到从主机B发来的ARP回复消息时,会用主机B的IP和MAC地址映射更新ARP缓存。本机缓存是有生存期的,生存期结束后,将再次重复上面的过程。主机B的MAC地址一旦确定,主机A就能向主机B发送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地址。
TCP
【源端口】- 16bit
来源处的端口号;
【目的端口】- 16bit
目的处的端口号;
【序号】- 32bit
每一个TCP报文段都会有一个序号,序号字段的值其实是本报文段所发送的数据的第一个字节的序号。这是因为TCP是面向连接的可靠服务,其每一个字节都会对应一个序号,通过序号来确保服务的可靠性和有序性。
【确认号】- 32bit
确认号,是期望收到对方的下一个报文段的数据的第一个字节的序号。(这句话有些拗口,但是在后面我们讲解三次握手和四次挥手时,大家会更深刻的理解这句话的含义)
【数据偏移】- 4bit
其实它本质上就是“首部长度”,因为“数据偏移”是指TCP报文段的数据部分的起始处距离TCP报文段的起始处的距离。(仍然很拗口,但相信你能明白)。
数据偏移总共占4bit,因此最大能表示的数值为15。而数据偏移的单位是“4字节”,此处的设计和IP数据报的设计是完全相同的,所以说TCP报文段首部的长度最长为15×4=60字节,且首部长度必须为4字节的整数倍。
【保留字段】- 6bit
这6bit在标准中是保留字段,我猜测,有两个目的,第一个是预留除URG/ACK/PSH/RST/SYN/FIN/之外的冗余功能位;第二个是为了对其字节位。
【紧急字段URG】- 1bit
此字段告诉系统此报文段中有紧急数据,应尽快传送。当URG=1时,
【确认字段ACK】- 1bit
当ACK=1时,表示确认,且确认号有效;当ACK=0时,确认号字段无效。
【推送字段PSH】- 1bit
当PSH=1时,则报文段会被尽快地交付给目的方,不会对这样的报文段使用缓存策略。
【复位字段RST】- 1bit
当RST为1时,表明TCP连接中出现了严重的差错,必须释放连接,然后再重新建立连接。
【同步字段SYN】- 1bit
当SYN=1时,表示发起一个连接请求。
【终止字段FIN】- 1bit
用来释放连接。当FIN=1时,表明此报文段的发送端的数据已发送完成,并要求释放连接。
【窗口字段】- 16bit
此字段用来控制对方发送的数据量,单位为字节。
一般TCP连接的其中一端会根据自身的缓存空间大小来确定自己的接收窗口大小,然后告知另一端以确定另一端的发送窗口大小。
【校验和字段】- 16bit
这个校验和是针对首部和数据两部分的。
【紧急指针字段】- 16bit
紧急指针指出在本报文段中的紧急数据的最后一个字节的序号。
UDP
UDP报头要比TCP的简单许多,只有区区8个字节,即源端口、目的端口、用户数据报长度、校验和。就凭这一点,就比TCP那复杂的20字节报头,要轻便了许多。
此处唯一需要解释一下的,就是“用户数据报长度”,它占了16位bit,能表示的最大长度是2^16,单位是字节。这里所指的长度,是包含UDP报头在内的总长度,而非数据部分的长度。
IP
4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4.
4位头部长度(header length): IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. 4bit表示最大的数字是15, 因此IP头部最大长度是60字节.
8位服务类型(Type Of Service): 3位优先权字段(已经弃用), 4位TOS字段, 和1位保留字段(必须置为0). 4位TOS分别表示: 最小延时, 最大吞吐量, 最高可靠性, 最小成本. 这四者相互冲突, 只能选择一个. 对于ssh/telnet这样的应用程序, 最小延时比较重要; 对于ftp这样的程序, 最大吞吐量比较重要.
16位总长度(total length): IP数据报整体占多少个字节.
16位标识(id): 唯一的标识主机发送的报文. 如果IP报文在数据链路层被分片了, 那么每一个片里面的这个id都是相同的.
3位标志字段: 第一位保留(保留的意思是现在不用, 但是还没想好说不定以后要用到). 第二位置为1表示禁止分片, 这时候如果报文长度超过MTU, IP模块就会丢弃报文. 第三位表示"更多分片", 如果分片了的话,最后一个分片置为1, 其他是0. 类似于一个结束标记.
13位分片偏移(framegament offset): 是分片相对于原始IP报文开始处的偏移. 其实就是在表示当前分片在原报文中处在哪个位置. 实际偏移的字节数是这个值 * 8 得到的. 因此, 除了最后一个报文之外, 其他报文的长度必须是8的整数倍(否则报文就不连续了).
8位生存时间(Time To Live, TTL): 数据报到达目的地的最大报文跳数. 一般是64. 每次经过一个路由, TTL-= 1, 一直减到0还没到达, 那么就丢弃了. 这个字段主要是用来防止出现路由循环
8位协议: 表示上层协议的类型
16位头部校验和: 使用CRC进行校验, 来鉴别头部是否损坏.
32位源地址和32位目标地址: 表示发送端和接收端.选项字段(不定长, 最多40字节): 略