您现在的位置: 主页 > MCU > 单片机技术应用 > 分析TCP/IP协议栈代码之IP & ICMP(STM32平台) -
本文所属标签:
为本文创立个标签吧:

分析TCP/IP协议栈代码之IP & ICMP(STM32平台) -

来源: 网络用户发布,如有版权联系网管删除 2018-09-06 

[导读]
1. IP介绍IP是TCP/IP协议族中最为核心的协议。大家,如TCP、UDP、ICMP及IGMP数据,都是在IP数据报格式基础上再封装一层再来传输的(见图1 - 4)。不可靠(unreliable)的意思是它不能保证 IP数据报能成

1. IP介绍

本文引用地址: http://www.21ic.com/app/mcu/201806/764630.htm

IP是TCP/IP协议族中最为核心的协议。大家,如TCP、UDP、ICMP及IGMP数据,都是在IP数据报格式基础上再封装一层再来传输的(见图1 - 4)。


不可靠(unreliable)的意思是它不能保证 IP数据报能成功地到达目的地。 IP仅提供最好的传输服务。如果发生某种错误时,如某个路由器暂时用完了缓冲区, IP有一个简单的错误处理算法:丢弃该数据报,然后发送 ICMP消息报给信源端。任何要求的可靠性必须由上层来提供(如TCP) 。

无连接(connectionless)这个术语的意思是I P并不维护任何关于后续数据报的状态信息。每个数据报的处理是相互独立的。这也说明, IP数据报可以不按发送顺序接收。如果一信源向相同的信宿发送两个连续的数据报(先是 A,然后是B) ,每个数据报都是独立地进行路由选择,可能选择不同的路线,因此B可能在A到达之前先到达。

2. IP首部

I P数据报的格式如图3 - 1所示。普通的IP首部长为20个字节,除非含有选项字段。


分析图3 - 1中的首部。最高位在左边,记为0 bit;最低位在右边,记为31 bit。4个字节的32 bit值以下面的次序传输:首先是0~7 bit,其次8~15 bit,然后1 6~23 bit,最后是24~31 bit。这种传输次序称作big endian字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。

目前的协议版本号是4,因此IP有时也称作IPv4。

服务类型(TOS)字段包括一个3 bit的优先权子字段(现在已被忽略) ,4 bit的TO S子字段和1 bit未用位但必须置0。4 bit的TO S分别代表:最小时延、最大吞吐量、最高可靠性和最小费用。

总长度字段是指整个I P数据报的长度,以字节为单位。

标识字段唯一地标识主机发送的每一份数据报。通常每发送一份报文它的值就会加 1。在大多数从伯克利派生出来的系统中,每发送一个I P数据报,I P层都要把一个内核变量的值加1,不管交给IP的数据来自哪一层。内核变量的初始值根据系统引导时的时间来设置。

TTL(time-to-live)生存时间字段设置了数据报可以经过的最多路由器数。TTL的初始值由源主机设置(通常为3 2或6 4) ,一旦经过一个处理它的路由器,它的值就减去1。当该字段的值为0时,数据报就被丢弃,并发送 ICMP报文通知源主机。

协议字段可以识别是哪个协议向I P传送数据。

首部检验和字段是根据IP首部计算的检验和码。它不对首部后面的数据进行计算。 ICMP、IGMP、UDP和TCP在它们各自的首部中均含有同时覆盖首部和数据检验和码。

目前,这些任选项定义如下:

? 安全和处理限制(用于军事领域,详细内容参见 RFC 1108[Kent 1991])

? 记录路径(让每个路由器都记下它的IP地址,见7 . 3节)

? 时间戳(让每个路由器都记下它的IP地址和时间,见7 . 4节)

? 宽松的源站选路(为数据报指定一系列必须经过的 IP地址,见8 . 5节)

? 严格的源站选路(与宽松的源站选路类似,但是要求只能经过指定的这些地址,不能经过其他的地址) 。

------------------------------------------以上内容整理于《TCP/IP协议详解:卷1》--------------------------------------

------------------------------------------以下内容产生于代码及分析--------------------------------------

3. IP宏定义实现

 C++ Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30


//*******IP*******
//IP首部长度
#defineIP_HEADER_LEN20

//IP版本号位置以太网首部2+6+6,与下面那个在用的时候上区别下
#defineIP_HEADER_LEN_VER_P0xe

//IP版本号位置以太网首部2+6+6
#defineIP_P0xe
//IP16位标志位置
#defineIP_FLAGS_P0x14
//IP生存时间位置
#defineIP_TTL_P0x16
//IP协议类型位置,如ICMP,TCP,UDP1个字节
#defineIP_PROTO_P0x17
//首部校验和
#defineIP_CHECKSUM_P0x18
//IP源地址位置14+12
#defineIP_SRC_P0x1a
//IP目标地址位置14+12+4
#defineIP_DST_P0x1e

//IP总长度
#defineIP_TOTLEN_H_P0x10
#defineIP_TOTLEN_L_P0x11

//协议类型
#defineIP_PROTO_ICMP_V0x01
#defineIP_PROTO_TCP_V0x06
#defineIP_PROTO_UDP_V0x11


4. IP函数实现

以太网的header在IP的header之前,很简单的,介绍先。

配置以太网的头,为14字节:6字节目的mac地址+6字节源mac地址+2字节协议类型

1
2
3
4
5
6
7
8
9
10
11
12
13


//makeareturnethheaderfromareceivedethpacket
voidmake_eth(unsignedchar*buf)
{
unsignedchari=0;

//copythedestinationmacfromthesourceandfillmymacintosrc
while(i{
buf[ETH_DST_MAC+i]=buf[ETH_SRC_MAC+i];
buf[ETH_SRC_MAC+i]=macaddr[i];
i++;
}
}


展开之后如下所示,其在以太网帧中的位置与之前的宏定义是一一对应的。


IP与ARP一样,需要判定是不是发给本机的(eth_type_is_ip_and_my_ip函数),还有与填充make_eth 函数一样需要填充函数(make_ip函数),此外还有填充其他杂七杂八和16位首部校验和函数(fill_ip_hdr_checksum函数)

C++ Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66


//判定过程与eth_type_is_arp_and_my_ip类似
unsignedchareth_type_is_ip_and_my_ip(unsignedchar*buf,unsignedintlen)
{
unsignedchari=0;

//eth+ip+udpheaderis42
if(len{
return(0);
}

if(buf[ETH_TYPE_H_P]!=ETHTYPE_IP_H_V||buf[ETH_TYPE_L_P]!=ETHTYPE_IP_L_V)
{
return(0);
}

if(buf[IP_HEADER_LEN_VER_P]!=0x45)
{
//mustbeIPV4and20byteheader
return(0);
}

while(i{
if(buf[IP_DST_P+i]!=ipaddr[i])
{
return(0);
}

i++;
}

return(1);
}
//下面那个ip填充函数调用它,主要是补充填充和校验和
voidfill_ip_hdr_checksum(unsignedchar*buf)
{
unsignedintck;
//clearthe2bytechecksum
buf[IP_CHECKSUM_P]=0;
buf[IP_CHECKSUM_P+1]=0;
buf[IP_FLAGS_P]=0x40;//don'tfragment
buf[IP_FLAGS_P+1]=0;//fragementoffset
buf[IP_TTL_P]=64;//ttl
//calculatethechecksum:
//校验和计算,在下下面那个函数里面,输入参数的含义下面看就晓得了
ck=checksum(&buf[IP_P],IP_HEADER_LEN,0);
buf[IP_CHECKSUM_P]=ck>>8;
buf[IP_CHECKSUM_P+1]=ck&0xff;
}

//makeareturnipheaderfromareceivedippacket
//与以太网填充函数类似,填充ip地址
voidmake_ip(unsignedchar*buf)
{
unsignedchari=0;

while(i{
buf[IP_DST_P+i]=buf[IP_SRC_P+i];
buf[IP_SRC_P+i]=ipaddr[i];
i++;
}

fill_ip_hdr_checksum(buf);
}

5. IP校验和实现

校验和函数式如何得出校验和值的呢?看《TCP/IP协议详解:卷1》里面咋说的吧。

”为了计算一份数据报的 IP检验和,首先把检验和字段置为 0。然后,对首部中每个 16 bit进行二进制反码求和(整个首部看成是由一串 16 bit的字组成) ,结果存在检验和字段中。当收到一份I P数据报后,同样对首部中每个16 bit进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中



              查看评论 回复



嵌入式交流网主页 > MCU > 单片机技术应用 > 分析TCP/IP协议栈代码之IP & ICMP(STM32平台) -
 

"分析TCP/IP协议栈代码之IP & ICMP(STM32平台) -"的相关文章

网站地图

围观()