icmp源代码 tcp/ip协议栈 c语言实现,分析TCP/IP协议栈代码之IP & ICMP(STM32平台) - 21ic电子网...

1. IP介绍

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

vM5bJQ449jOAf4V5yg

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

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

2. IP首部

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

CbxSw

分析图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++ Code1

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++;

}

}

LmI4VzMWDxOoSgJKmXzf+cbKDZlfYEmO7gJCDjyxYRgoc2tNXjK0jbwxw

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

cmtXREAcQ

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

C++ Code1

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进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值