以太网网络协议


1 IPv4协议部分

先来一个大体的架构图:

以太网网络协议_第1张图片
tcp/ip协议栈

1.1 MAC

关于MAC部分的数据协议,如下图所示:


以太网网络协议_第2张图片
1.png
协议类型
IP 0x0800
ARP 0x0806
RARP 0x8035
以太网网络协议_第3张图片
2.png
以太网网络协议_第4张图片
3.png

1.2 ARP

ARP数据包格式如下图所示:

以太网网络协议_第5张图片
ARP.png

ARP数据为42字节长度(不包含CRC)(在wireshark上显示的为这个长度)。

下面是一些解释性的说明:

  • 硬件类型表示硬件地址类型。值为1,表示以太网地址。
  • 协议类型表示要映射的协议地址类型。值为0x8000表示IP地址。该值与包含IP数据报的以太网数据帧中的类型字段的值相同。
  • 硬件地址长度,对于以太网上的IP地址的ARP请求或应答来说,值为6。
  • 协议地址长度,对于以太网上的IP地址的ARP请求或应答来说,值为4。
  • 操作字段指出4种操作类型。ARP请求为1,ARP应答为为2,RARP请求为3,RARP应答为4。

从整个协议来看,后面的28字节不符合以太网数据包最小数据长度为46字节,所以会有填充,填充18字节的数据长度。

在做网络底层应用的时候,该协议肯定是需要首先实现的。现在说明一下:
我的PC机MAC地址为:

在windows上的cmd下输入命令:

$ ipconfig /all

以太网网络协议_第6张图片
ip地址

在windows下的cmd下继续输入命令:

$ ping 192.168.25.15 -t

在使用stm32+ENC28J60网卡后,可以看到收到的数据长度为60,这是因为arp数据经过网卡的时候,是被补齐为64字节的数据,后在ENC28J60中,踢掉了4个字节的CRC数据。

截图如下:

ARP接收的数据
数据 偏移 字节数 含义
0xff 0xff 0xff 0xff 0xff 0xff 0 6 以太网的目的地址,从这里可以看出为广播地址
0xb0 0x83 0xfe 0x95 0xd6 0x7d 6 6 以太网源地址,也就是PC上的物理地址
0x8 0x6 12 2 帧类型,从前面说的协议类型来看,这里表示的是ARP协议
0x0 0x1 14 2 硬件类型,为1,表示的是以太网地址
0x8 0x0 16 2 协议类型,这表示的是IP地址
0x6 18 1 6,没什么可说的
0x4 19 1 没什么可以说的
0x0 0x1 20 2 操作字段,ARP请求为1,应答为2
0xb0 0x83 0xfe 0x95 0xd6 0x7d 22 6 发送端以太网地址
0xc0 0xa8 0x19 0xa 28 4 发送端ip地址,也就是192.168.25.10
0x0 0x0 0x0 0x0 0x0 0x0 32 6 目的以太网地址
0xc0 0xa8 0x19 0xf 38 4 目的ip地址,也就是192.168.25.15

当然了,PC端自己也会不间断的向192.168.25.1请求ARP。

如果要做密码破解,可以尝试hydra工具。

我截出一部分我使用程序接收到的数据:


以太网网络协议_第7张图片
程序接收的数据

1.3 IP

IP数据包格式如下图所示:


以太网网络协议_第8张图片
4.png

从图上看来,其包含20字节的头部数据。

各个字段与其含义还是说明一下:

字段 含义
版本号 IP协议的版本号。一般的值为0100(IPv4),0110(IPv6)
IP包头长度 长度4比特,单位为32bit(4个字节)。IP包头最小长度为20字节。
服务类型 长度为8比特
IP包总长 长度16比特,以字节为单位计算的IP包的长度 (包括头部和数据)
标识符 长度16比特,对较大的上层数据包进行分段(fragment)操作
标记 长度3比特
片偏移 长度13比特,表示该IP包在该组分片包中位置,接收端靠此来组装还原IP包
生存时间 长度8比特,这个字段可以防止由于路由环路而导致IP包在网络中不停被转发。
8位协议 长度8比特,标识了上层所使用的协议,详情见下一个表
16位首部校验和 长度16比特,用来做IP头部的正确性检测,但不包含数据部分
源IP地址 长度32比特,除非使用NAT,否则整个传输的过程中,该地址不会改变。
目的IP地址 长度32比特,除非使用NAT,否则整个传输的过程中,该地址不会改变。
偏移 字节数 含义
14 1 4位的版本,4位的首部长度
15 1 8位的服务类型(TOS)
16 2 16位总长度(字节数),包含IP首部和IP数据部分
18 2 16位标识
20 2 3位标志,13位片偏移
22 1 8位生存时间
23 1 8位协议
24 2 16位首部校验和,不对首部后面的数据进行计算
26 4 32位源IP地址
30 4 32位目的IP地址

3位标记和13位片偏移要稍微说一点:

  • 3位标志,目前只有2位是有意义的。
    最低位为MF(More Fragment)。MF=1即表示后面“还有分片”的数据报。MF=0表示这已是若干数据报片中的最后一个。
    中间的一位记为DF(Don't Fragment),意思是“不能分片”。只有当DF=0时才允许分片。
  • 片偏移指出:较长的分组在分片后,某片在原分组中的相对位置。也就是说,相对于用户数据字段的起点,该片从何处开始。片偏移以8个字节为偏移单位。也就是说,每个分片的长度一定是8字节(64位)的整数倍。
以太网网络协议_第9张图片
5.png

8位协议字段取值如下(关键的几个):

数值 值描述
1 ICMP
2 IGMP
6 TCP
17 UDP

接着上面的ARP继续看,到IP首部,已经是从第14个字节开始了。所以协议字段,是在第24位上。

1.4 ICMP

ICMP数据包格式如下:


以太网网络协议_第10张图片
icmp-1.png
以太网网络协议_第11张图片
icmp-2.png
以太网网络协议_第12张图片
icmp-3.png
以太网网络协议_第13张图片
icmp-4.png
以太网网络协议_第14张图片
icmp-5.png
以太网网络协议_第15张图片
icmp-6.png

还是贴出来,从PC机上发送给STM32+ENC28J60上接收到的数据包:

以太网网络协议_第16张图片
ICMP实际数据包
数据 偏移 字节数 含义
0x54 0x55 0x58 0x10 0x0 0x24 0 6 目的地址
0xb0 0x83 0xfe 0x95 0xd6 0x7d 6 6 源地址
0x8 0x0 12 2 帧类型,表示的是IP数据报
0x45 14 1 4表示的是4位版本号,5表示的是首部长度,也就是5x4=20字节
0x0 15 1 服务类型
0x0 0x3c 16 2 IP包总长,也就是60字节
0x4c 0xfd 18 2 是标识符,进行的分段操作,可以看到该值一直在递增
0x0 0x0 20 2 标记为0,片偏移也为0,表明未分段
0x80 22 1 表示TTL=128
0x1 23 1 表示的是8位的协议,1表示ICMP
0x3a 0x5a 24 2 表示的是IP头部的校验和
0xc0 0xa8 0x19 0xa 26 4 源ip地址
0xc0 0xa8 0x19 0xf 30 4 目的ip地址
0x8 0x0 34 2 将类型和代码组合起来,表示请求回显(ping请求)
0x44 0xcc 36 2 校验和
0x0 0x1 38 2 标识符
0x8 0x8f 40 2 序号
0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x6a 0x6b 0x6c 0x6d 0x6e 0x6f 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 42 32 数据

1.5 ping

ping数据包格式如下图所示:


以太网网络协议_第17张图片
ping-1.png

是ICMP中的一部分功能实现。

对于工程师来说,调试网络程序,这个部分是必须要调通的。
那么就以此为例,来谈谈一些步骤性的内容:

icmp是在网络的第三层:网络层上的。每一个数据包都含有一个MAC地址。而且该地址是全球唯一的。

ping从主机发送出去后:

  • 通过ARP解析对应ip地址的MAC编号。主机先查一下自己的ARP高速缓存表(最近数据传递更新的IP-MAC地址对应表),如果查询的IP-MAC值对不存在,那么主机就向网络广播一个ARP请求包,这个包里面就有待查询的IP地址,而直接收到这份广播的包的所有主机都会查询自己的IP地址,如果收到广播包的某一个主机发现自己符合条件,那么就回应一个ARP应答包(将自己对应的IP-MAC对应地址发回主机),源主机拿到ARP应答包后会更新自己的ARP缓存表。源主机根据新的ARP缓存表准备好数据链路层的的数据包发送工作。
  • 回复icmp包。

对于ping数据包来说,正常的长度应该是:

目的地址+源地址+类型+IP首部+ICMP报文(8字节+选项数据)+CRC
=6+6+2+20+8+选项数据+4 = 46 + 选项数据。
若不包含CRC,则长度为:42 + 选项数据。(在wireshark上显示的为这个长度)

接着上面icmp分析到这里的ping协议包。

这里有一个比较重要的内容,也就是校验和。
IP,ICMP,UDP,TCP的报文头都有校验和字段,大小都为2字节,它们的算法也是一样的。

  • 在发送数据的时候,为了计算数据包的校验和,需要按照这样的步骤:
    1.把校验和的字段置为0。
    2.把需校验的数据,看成以16位为单位的数字组成,依次进行二进制反码求和。
    3.把得到的结果存入校验和字段中。
  • 在接收数据的时候, 可以按照如下步骤:
    1.把首部看成以16位为单位的数字组成,依次进行二进制的反码求和,包括校验和字段。
    2.检查计算出的校验和的结果是否为0。
    3.如果等于0,说明校验和是正确的。否则,校验和是错误的,协议栈就要抛弃这个数据包。

关于这个部分,我就说一个例子程序来理解即可:

  buf[34] = 0;

                {
                    unsigned int i_temp = (buf[36] << 8) + buf[37] ;
                    
                    i_temp = i_temp + 0x0800;
                    buf[36] = (i_temp >> 8) & 0xff;
                    buf[37] = i_temp & 0xff;
                    if(i_temp >> 16 )
                          buf[37] += 1;

                }

在这个代码里面,PC机发送了一个ping命令,STM32+ENC28J60需要返回数据包,由于在pc机发送的数据里面,buf[34]=0x08,而返回的数据buf[34]=0x0。再根据校验和计算的规则,需要将数据取反发送,也就是说,其实buf[36],buf[37]的校验和会将buf[34]计算成0xf7,那么我现在发送的数据其实为0x0的去反结果0xff,所以,需要将最后的结果加上的数据为0x0800。

当然,为了取巧,可以使用更简单的实现方法:

            {
                if(buf[37] > 0xff-0x8)
                    buf[37] += 1;
                 buf[36] += 0x8;     
            }

上面,这两种都是一个取巧的办法。

前面其实已经详细说明了整个包的长度。这里再点名一下,前面1.1 MAC中说明的是整个包的协议格式。现在这一节主要是说的IP数据包。所以,ICMP包是在6+6+2+20=34字节位置上的。

点明该问题的原因是现在需要具体计算ICMP的校验和。

我在这里列出来:


以太网网络协议_第18张图片
ICMP协议包

校验和代码:

unsigned short checksum(unsigned short *buf,int nword)
{
        unsigned long sum;
        for(sum=0;nword>0;nword--)
        {
                sum += *buf++;
                sum = (sum>>16) + (sum&0xffff);
        }
        return ~sum;
}

整个源码:

#include 

unsigned short checksum(unsigned short *buf,int nword)
{
        unsigned long sum;
        for(sum=0;nword>0;nword--)
        {
                sum += *buf++;
                sum = (sum>>16) + (sum&0xffff);
        }
        return ~sum;
}

int main(int argc,char *argv[])
{
        int i = 0;
        int len = 0;
        unsigned short crc = 0;

        unsigned short arr2[]={0x0800,0x0000,0x0001,0x0017,0x6162,0x6364,0x6566,0x6768,0x696a,
        0x6b6c,0x6d6e,0x6f70,0x7172,0x7374,0x7576,0x7761,0x6263,0x6465,0x6667,0x6869};

        len = sizeof(arr2)/sizeof(arr2[0]);
        printf("len:%d\r\n",len);

        crc= checksum(arr2,len);
        printf("crc:0x%0x\r\n",crc);

        return 0;
}

以太网网络协议_第19张图片
计算结果

现在我们可以构造回复包。在构造回复包前,可以先看看正常的网络是如何回应的,这样心里有一个数。

icmp请求与回复包

请求包:


以太网网络协议_第20张图片
icmp请求包

回复包:


以太网网络协议_第21张图片
icmp回复包

这里面有一个IP头校验,其实跟前面一样,先把校验和位置填0,然后将IP首部的20字节数据变成16位加起来,取反然后放到校验和位置即可。

贴上源代码:

#include 
unsigned short checksum(unsigned short *buf,int nword)
{
        unsigned long sum;
        for(sum=0;nword>0;nword--)
        {
                sum += *buf++;
                sum = (sum>>16) + (sum&0xffff);
        }
        return ~sum;
}

int main(int argc,char *argv[])
{
        int i = 0;
        int len = 0;
        unsigned short crc = 0;

        unsigned short arr2[]={0x0800,0x0000,0x0001,0x0017,0x6162,0x6364,0x6566,0x6768,0x696a,
        0x6b6c,0x6d6e,0x6f70,0x7172,0x7374,0x7576,0x7761,0x6263,0x6465,0x6667,0x6869};

        unsigned short arr3[] = {0x4500,0x003c,0xa0c4,0x0000,0x4001,0x0000,0xc0a8,0x7b01,0xc0a8,
        0x7bc1};

        len = sizeof(arr3)/sizeof(arr3[0]);
        printf("len:%d\r\n",len);

        crc= checksum(arr3,len);
        printf("crc:0x%0x\r\n",crc);

        return 0;
}

执行结果如下:


IP首部校验和

注意:ICMP包上有一个序号。在偏移40,41位上。

写到这里,就算结束了,本来这里需要标上红字的,可是没发标啊。。。

!!!注意:!!!!

如果在程序中开启了硬件校验,那么我们就不需要填写校验位了,简单来说,只需要关注数据,算法等不用管!!!!!

讲解玩这些,上一个图,表明一下ping的速度:


以太网网络协议_第22张图片
ping数据包

1.6 UDP

UDP数据包格式如下图所示:


以太网网络协议_第23张图片
udp-1.png
以太网网络协议_第24张图片
udp-2.png

UDP数据包的头部长度为8字节。

偏移 字节数 含义
0 34 以太网目的地址,以太网源地址,帧类型,IP首部 等
34 2 16位源端口号
36 2 16位目的端口号
38 2 16位UDP长度
40 2 16位UDP校验和

这里的IP首部没有列出来,不是说不重要,而是前面已经列出来了。在IP首部,偏移为第24位有一个8位的协议字段,也就是UDP的标识。

关于校验和的计算方法,参考资料如下:
1)链接1
2)链接2
3)链接3
补码形式有1的补码和2的补码,其中1的补码用在IP、TCP的校验和中;
1的补码算法如下,公式:
~N = (2^n -1) - N,n是每一个字节的1的个数,N是正整数。
~N是-N在1的补码下的记法。
例如,有一个8bit的字节和N=6,我们则有:
~N = (2^8 -1) - 6 = 255 - 6 = 249 = 11111001

使用1的补码好处有两点:
1.大小端无影响。
2.计算传输和验证校验和比较简单。

但是,要补充一句,使用这种校验和方法,并不是说一定是无差错,可靠的。比如说一个字节上的两个比特数据都反向了,那么,你有好处也没用。当然,这种情况出现的可能性太低了。

udp包构造起来比较简单,不过要注意几个地方:

unsigned char udp_buf[]={
    0x00, 0xe0, 0x4c, 0x08, 0xcd, 0x77, 0x02, 0x00,            0x00, 0x01, 0x02, 0x03, 0x08, 0x00, 0x45, 0x00,     
  0x00, 0x32,/*len1*/ 0xa0, 0xc4, 0x00, 0x00, 0x40, 0x11/*udp*/,     0x00, 0x00, 0xc0, 0xa8, 0x01, 0x03, 0xc0, 0xa8,     
    0x01, 0x02, 0x12, 0x34, 0xc3, 0x50, 0x00, 0x1e,/*len2*/     0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
  0x07, 0x08,   0x01, 0x02, 0x03, 0x04, 0x05, 0x06,            0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
};

例如上面数组标注出来的,len1是整个ip部分的长度,也就是16*3+2=50。len2是数据部分+udp首部8字节。标注的udp是协议类型。

后面,网卡只需要发送该数据,就能将数据发送给udp服务器了。

1.7 TCP

以太网网络协议_第25张图片
tcp-1.png
以太网网络协议_第26张图片
tcp-2.png

TCP的头部和UDP头部不同,现大体分析如下:

偏移 字节数 含义
0 34 以太网目的地址,以太网源地址,帧类型,IP首部 等
34 2 16位源端口号
36 2 16位目的端口号
38 4 32位序号
42 4 32位确认序号
46 2 4位首部长度,6位保留,然后是URG,ACK,PSH,RST,SYN,FIN
48 2 16位窗口大小
50 2 16位校验和,包含TCP首部和TCP数据,还需加上12字节的伪首部
52 2 16位紧急指针
54 4 可选字段,常见的是最长报文大小,称为MSS

关于MSS段,取值不限于以下,但常见的如下所示:

以太网网络协议_第27张图片
MSS段可选内容

在IP首部,整个数据包的第24位上,TCP的8位协议字段为6。

以太网网络协议_第28张图片
12字节的伪首部

对这部分还需要稍作说明:
上面列出来了需要计算的数据部分,但是,并不是说,在编写程序的时候,严格按照这个图来做,那思想就太呆板了,我们可以看到Source address,Destination address是在IP首部中的,我们就可以把Zeros,Protocol,TCP Length单独拿出来,做校验而已。其他的就按照"IP首部+TCP首部+数据"来做校验即可。

关于这个部分,还是需要贴出代码做示例:

        if(( buf[0x17] == 6 )) 
        {
            unsigned int seq;
            unsigned int ack;

            printf("\r\nxxxxxxxxxxx   TCP protocol xxxxxxxxxxxx  \r\n ");

           //第一次握手,返回数据
            if(buf[47] & 0x02) 
            {
                //以太网目的地址
                buf[0] = buf[6]; 
                buf[1] = buf[7]; 
                buf[2] = buf[8]; 
                buf[3] = buf[9]; 
                buf[4] = buf[10]; 
                buf[5] = buf[11]; 
                //以太网源地址
                buf[6] = mymac[0];
                buf[7] = mymac[1];
                buf[8] = mymac[2];
                buf[9] = mymac[3];
                buf[10] = mymac[4];
                buf[11] = mymac[5];
                //帧类型,不用管
    
    
                    //32位目的ip地址
                    buf[30] = buf[26];
                    buf[31] = buf[27];
                    buf[32] = buf[28];
                    buf[33] = buf[29];
                    //32位源ip地址
                    buf[26] = myip[0];
                    buf[27] = myip[1];
                    buf[28] = myip[2];
                    buf[29] = myip[3];
    
                //IP首部
                    //16位总长度  IP头部+数据(TCP首部)
                    buf[16] = (20 + 20 + 4) >> 8;
                    buf[17] = (20 + 20 + 4) & 0xff;
                    //16位首部校验和
                    {
                        int i = 0,len = 0;
                        unsigned int sum = 0;
                        //先对校验和位置清0
                        buf[24]=0;
                        buf[25]=0;
                        //3位标志,13位偏移
                        buf[20]=0x40;
                        buf[21]=0x00;
                        buf[22]=64;
    
                        len = 20;
                        for(i = 0 ; i < len ; i = i + 2)
                        {
                            sum += (buf[14+i] << 8 ) | (buf[14+i+1]);
                        }  
                        if(sum >> 16)
                        {
                            sum = (sum >> 16) + (sum & 0xffff);
                        }
                        sum = sum^0xffff;
    
                        buf[24]  = (sum >> 8) & 0xff;
                        buf[25]  = sum & 0xff;
    
                    }
    
    
                //TCP首部
    
    
                    //16位目的端口号
                    buf[36] =  buf[34];
                    buf[37] =  buf[35];
    
                    // 16位源端口号
                    buf[34] = (6000 >> 8)&0xff ;
                    buf[35] = 6000 & 0xff;
    
                    //32 位序号
                    seq = (buf[38] << 24) | (buf[39] << 16) | (buf[40] << 8) | (buf[41]);
                    //printf("seq:%0x\n",seq);
                    buf[38] = (myseq >> 24) & 0xff;
                    buf[39] = (myseq >> 16) & 0xff;
                    buf[40] = (myseq >> 8 ) & 0xff;
                    buf[41] = myseq & 0xff;
                    myseq ++;
                    //32 位确认号
                    seq = seq + 1;
                    buf[42] =  (seq >> 24) & 0xff;
                    buf[43] =  (seq >> 16) & 0xff;
                    buf[44] =  (seq >>  8) & 0xff;
                    buf[45] =  seq & 0xff;
                    
                    //TCP的首部数据长度
                    buf[46] = 0x60;
                    //ACK,PSH,等
                    buf[47] = 0x12;
    
                    //16位窗口大小
                    //ignore
    
                    //可选字段内容
                    buf[54] =  2;/*kind*/
                    buf[55] =  4;/*len*/
                    buf[56] =  0x05;/*最大报文长度1460,也就是0x05b4*/
                    buf[57] =  0xb4;
    
                    //16位校验和,该位应该最后计算。
                    {
                        int i=0;
                        unsigned int sum=0;
                        int len;
                        //先将校验和部分清0
                        buf[50] = 0;
                        buf[51] = 0;
                        //将所有数据拼成16bit,然后做检验和,注意,这里
                        //是从IP首部中的32位源地址开始的
                        len = 8 + 20 + 4;
    
                        sum = /*protocol*/ 6 + /*TCP length*/ (20 + 4);
                        for(i = 0 ; i < len ; i = i + 2)
                        {
                            sum += (buf[26 + i] << 8) | (buf[26+i+1]); 
                        }
                        if(sum >> 16)
                        {
                            sum = (0xffff&sum) + (sum>> 16);
                        }
                        sum = sum^0xffff;
    
                        buf[50] = (sum>>8)&0xff;
                        buf[51] = sum&0xff;
                    }
                    //16位紧急指针
                    enc28j60PacketSend(14+20+20+4,buf);  //长度为: ETH头+IP首部+TCP首部
                 continue;
                }
            }

这里面涉及到IP首部校验和,TCP校验和的计算。还有就是MSS的设计。这里设置的数据长度为1460。

再来看看TCP建立连接等几个重要标识的含义:

标识 含义
URG TCP包的紧急指针域有效,用来保证TCP连接不被中断,并且督促中间层设备要尽快处理这些数据
ACK 表示应答域有效,就是说前面所说的TCP应答将会包含在TCP数据包中;为1的时候表示应答域有效,反之为0
PSH 表示push操作。就是指在数据包到达接收端以后,立即传送给应用程序, 而不是在缓冲区中排队
RST 表示连接复位请求。用来复位那些产生错误的连接,也被用来拒绝错误和非法的数据包
SYN 表示同步序号,用来建立连接
FIN 表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送FIN标志位的TCP数据包后,连接将被断开

protocol表示的是传输层的协议号,TCP为6。TCP的报文长度(TCP报头+数据)。伪首部的作用是增强TCP校验和的检错能力。

TCP的信息流有3次握手和4次分手机制,如果没有握手,客户端和服务器是链接不起来的,如下图所示:

以太网网络协议_第29张图片
TCP交互机制

现在来说说三次握手,这个是必须要掌握的,这部分内容最好使用wireshark来验证:

1.建立连接。主机发送连接请求报文段,SYN=1,Seq=x,客户端进入SYN_SENT状态,等待服务器的确认。
2.服务器收到SYN报文。服务器收到SYN报文后,需要对SYN报文进行确认。设置ACK=x+1,Seq=y,同时还需要发送SYN=1信息,这个时候,服务器进入SYN_RCVD状态。
3.客户端收到SYN+ACK报文段。ACK=y+1,向服务器发送ACK报文段,发送完毕后,客户端和服务器都进入ESTABLISHED状态,完成3次握手。

在三次握手过程中,有一项数据内容是需要注意的:
MSS:
最大消息长度,也就是maximum segment size。最理想的情况下,最大消息长度正好是IP中不会被分片处理的最大数据长度。

下面是数据发送过程:

最后是四次分手过程:

这几个内容,可以用一个状态迁移图来表示:

以太网网络协议_第30张图片
TCP状态迁移图

以上这些,就能达成所谓TCP的可靠性传输,总的来说,包括以下几点:

1.使用校验和
2.使用序列号
3.使用确认应答
4.使用重发机制
5.使用连接管理
6.使用窗口控制

1.8 DNS

报文是由12字节长的首部和4个长度可变的字段组成。

以太网网络协议_第31张图片
DNS协议格式.png
  • 标识字段:客户程序设置并由服务器返回结果。客户程序通过它来确定响应与查询是否匹配。详情见下面的内容。
  • 随后的4个16bit字段说明4个变长字段中包含的条目数。对于查询报文,问题数通常是1,其他三项均为0。类似的,对于应答报文,回答数至少是1,剩下的两项可以是0或非0。

标识字段:

以太网网络协议_第32张图片
标识字段.png
名字 长度 功能
QR 1B 0表示查询报文,1表示响应报文
OPCODE 4B 0表示标准查询,1表示反向查询,2表示服务器状态请求
AA 1B 表示授权回答
TC 1B 表示可截断的,使用UDP表示应答的总长度超过512字节时,只返回前512字节
RD 1B 表示期望递归,能在一个查询中设置,在响应中返回,有递归查询和迭代查询
RA 1B 表示可用递归
xxx 3B 必须设置为0
rcode 4B 通常为0(没有差错)和3(名字差错)

1.8.1 DNS查询报文中的问题部分

以太网网络协议_第33张图片
DNS查询报文.png
  • 查询名是要查找的名字。它是一个或多个标识符的序列。每个标识符以首字节的计数值来说明随后标识符的字节长度。每个名字以最后字节为0结束。长度为0的标识符是根标识符。计数值为0~63。

1.8.2 DNS响应报文中的资源记录部分

DNS报文中最后的三个字段,回答字段、授权字段和额外信息字段,均采用一种称为资
源记录RR(Resource Record)的相同格式。
如下图所示:

以太网网络协议_第34张图片
DNS资源记录格式.png
  • 域名:记录中资源数据对应的名字。格式和前面介绍的查询名字段格式相同。
  • 类型:是RR的类型码。和查询类型值一样。
  • 类:通常为1,指Internet数据。
  • 生存时间:客户程序保留该资源记录的秒数。资源记录通常的生存时间为2天。
  • 资源数据长度:资源数据的数量。依赖于类型字段的值,对于类型1(A记录)资源数据是4字节的IP地址。

1.9 IGMP

是Internet组管理协议。用于支持主机和路由器进行多播的Internet组管理协议。可以让一个物理网络上所有系统知道主机当前所在的多播组。多播路由器需要这些信息以便知道多播数据应该向哪些接口转发。IGMP有固定的报文长度,没有可选数据。如下所示:

以太网网络协议_第35张图片
IGMP报文封装在IP数据报中.png
以太网网络协议_第36张图片
IGMP报文的字段格式.png

1.10 UDP-Lite

即Lightweight User Datagram Protocol,轻量级用户数据报协议,是扩展UDP机能的一种传输层协议。它更加适应于网络的差错率比较大,但是应用对轻微差错不敏感的情况,例如实时视频的播放等。

1.11 SCTP

即Stream Control Transmission Protocol,流控制传输协议。
其特征如下:

1.以消息为单位收发
2.支持多重宿主
3.支持多数据流通信
4.可以定义消息的生存期限

1.12 DDCP

即Datagram Congestion Control Protocol,数据报拥塞控制协议,是一个辅助UDP的崭新的传输层协议。

2 IPv6部分

事先说明,IPv6的设计者将该协议建立在IPv4基础上,沿用IPv4工作良好的部分,改进可以工作的部分,去掉影响性能和功能的部分,还增加了当前特别需要的功能。

3 待续

你可能感兴趣的:(以太网网络协议)