当前位置:首页 > 单片机 > 单片机
[导读] 1.前言 嵌入式以太网开发是一个很有挑战性的工作。通过几个月的学习,我个人觉得大致有两条途径。第一条途径,先通过高级语言熟悉socket编程,例如C#或C++,对bind,listen,connect,accept等函数熟悉

1.前言

嵌入式以太网开发是一个很有挑战性的工作。通过几个月的学习,我个人觉得大致有两条途径。第一条途径,先通过高级语言熟悉socket编程,例如C#或C++,对bind,listen,connect,accept等函数熟悉之后,应用 lwIP。第二种途径,通过分析嵌入式以太网代码,结合TCPIP协议栈规范逐步实践代码。第一种途径效率高,开发周期短,编写出来的代码性能稳定,第二种途径花的时间长,开发出来的代码功能不完善,但是由于紧紧结合TCPIP规范,可以了解的内容较多,适合学习。本文通过分析和修改AVRNET源码,逐步实现TCPIP协议栈的各个子部分,包括ETHERNET部分,ARP部分,IP部分,ICMP部分,UDP部分,TCP部分和HTTP部分。

本文将实现IP部分和ICMP部分。

1.2 相关资料

【ENC28J60学习笔记】

STM32NET学习笔记 ARP和Ethernet部分】

【AVRNET项目(国外)】

【AVR webserver项目(国外)】


1.3 代码仓库

【代码仓库】——CSDN Code代码仓库。


2.IP部分实现

IP层是TCP和UDP实现的基础。IP首部紧跟以太网首部,长度为20字节。IP首部具有最基本的两个任务,

【第一】定义IP包的具体协议类型,例如ICMP,TCP或UDP等;

【第二】定义IP报文从哪个IP地址来和到哪个IP地址去。

需要强调,在同一个子网中即同一个物理网络中,IP报文中的目标IP地址和以太网首部中的目标MAC地址相对应,若不在同一个物理网路中,目标IP地址和目标MAC地址不同,目标MAC地址被路由器的MAC地址替代,意味着通过路由器转发报文。在IP首部中还包括很多其他内容,需要注意的是IP标识符,该标识符主要用于区分IP报文,最简单的算法即每发送一个IP报文后IP标识符累加。具体通过以下代码实现IP首部的填充。

2.1 IP首部填充


  1. //IP首部总长度

  2. #defineIP_HEADER_LEN20

  3. //协议类型

  4. //ICMP协议

  5. #defineIP_PROTO_ICMP_V0x01

  6. //TCP协议

  7. #defineIP_PROTO_TCP_V0x06

  8. //UDP协议

  9. #defineIP_PROTO_UDP_V0x11

  10. //IPV4版本

  11. #defineIP_V4_V0x40

  12. #defineIP_HEADER_LENGTH_V0x05

  13. //IP版本号位置以太网首部2+6+6

  14. #defineIP_P0x0E

  15. //首部长度

  16. #defineIP_HEADER_VER_LEN_P0x0E

  17. //服务类型

  18. #defineIP_TOS_P0x0F

  19. //IP总长度

  20. #defineIP_TOTLEN_H_P0x10

  21. #defineIP_TOTLEN_L_P0x11

  22. //IP标识

  23. #defineIP_ID_H_P0x12

  24. #defineIP_ID_L_P0x13

  25. //

  26. #defineIP_FLAGS_H_P0x14

  27. #defineIP_FLAGS_L_P0x15

  28. //TTL生存时间

  29. #defineIP_TTL_P0x16

  30. //IP协议类型例如ICMPTCPUDP

  31. #defineIP_PROTO_P0x17

  32. //首部校验和

  33. #defineIP_CHECKSUM_H_P0x18

  34. #defineIP_CHECKSUM_L_P0x19

  35. //源IP地址

  36. #defineIP_SRC_IP_P0x1A

  37. //目标IP地址

  38. #defineIP_DST_IP_P0x1E

  39. voidip_generate_header(BYTE*rxtx_buffer,WORD_BYTEStotal_length,BYTEprotocol,BYTE*dest_ip)

  40. {

  41. BYTEi;

  42. //校验结果

  43. WORD_BYTESck;

  44. //版本号和首都长度

  45. rxtx_buffer[IP_P]=IP_V4_V|IP_HEADER_LENGTH_V;

  46. //服务类型

  47. rxtx_buffer[IP_TOS_P]=0x00;

  48. //总长度

  49. rxtx_buffer[IP_TOTLEN_H_P]=total_length.byte.high;

  50. rxtx_buffer[IP_TOTLEN_L_P]=total_length.byte.low;

  51. //IP标识

  52. rxtx_buffer[IP_ID_H_P]=ip_identfier>>8;

  53. rxtx_buffer[IP_ID_H_P]=ip_identfier&0x00ff;

  54. //累加

  55. ip_identfier++;

  56. //标志和分片偏移

  57. rxtx_buffer[IP_FLAGS_H_P]=0x00;

  58. rxtx_buffer[IP_FLAGS_L_P]=0x00;

  59. //生存时间

  60. rxtx_buffer[IP_TTL_P]=128;

  61. //setippackettypetotcp/udp/icmp...

  62. rxtx_buffer[IP_PROTO_P]=protocol;

  63. //设定目标地址和源地址

  64. for(i=0;i<4;i++)

  65. {

  66. rxtx_buffer[IP_DST_IP_P+i]=dest_ip[i];

  67. rxtx_buffer[IP_SRC_IP_P+i]=avr_ip.byte[i];

  68. }

  69. //校验结果

  70. rxtx_buffer[IP_CHECKSUM_H_P]=0;

  71. rxtx_buffer[IP_CHECKSUM_L_P]=0;

  72. ck.word=software_checksum(&rxtx_buffer[IP_P],sizeof(IP_HEADER),0);

  73. rxtx_buffer[IP_CHECKSUM_H_P]=ck.byte.high;

  74. rxtx_buffer[IP_CHECKSUM_L_P]=ck.byte.low;

  75. }



2.2 IP报文查询

IP报文查询功能对应于ARP报文查询功能,通过以太网首部中的最后2个字节判断该报文是否为IP报文;如果是IP报文则继续和本机IP地址相比较。如果两步检查均通过则认为是合法的IP报文,当然这其中舍弃了IP版本号和首部校验和的检查,虽然存在某些隐患但并不妨碍实现基本功能。


  1. BYTEip_packet_is_ip(BYTE*rxtx_buffer)

  2. {

  3. unsignedchari;

  4. //检查该报文是否为IP报文

  5. if(rxtx_buffer[ETH_TYPE_H_P]!=ETH_TYPE_IP_H_V||rxtx_buffer[ETH_TYPE_L_P]!=ETH_TYPE_IP_L_V)

  6. return0;

  7. //检查该报文的IP地址是否为本机IP地址,逐个检查

  8. for(i=0;i

  9. {

  10. if(rxtx_buffer[IP_DST_IP_P+i]!=avr_ip.byte[i])

  11. return0;

  12. }

  13. //若该报文为IP报文,且目标IP地址为本机地址,返回1

  14. return1;

  15. }



3.ICMP部分实现

虽然ICMP具有很多的子协议,但是其中最著名的要数ping程序,即ICMP回显请求和应答报文。通过使用ping命令来判断报文是否可以到达目标地址。ICMP的实现是一个逐步遵守规则的过程,即向固定的字节填充数据。


  1. //回显应答

  2. #defineICMP_TYPE_ECHOREPLY_V0

  3. //回显请求

  4. #defineICMP_TYPE_ECHOREQUEST_V8

  5. //ICMP首部长度

  6. #defineICMP_PACKET_LEN40

  7. //ICMP类型

  8. #defineICMP_TYPE_P0x22

  9. //ICMP代码

  10. #defineICMP_CODE_P0x23

  11. //ICMP首部校验和

  12. #defineICMP_CHECKSUM_H_P0x24

  13. #defineICMP_CHECKSUM_L_P0x25

  14. //ICMP标识符

  15. #defineICMP_IDENTIFIER_H_P0x26

  16. #defineICMP_IDENTIFIER_L_P0x27

  17. //ICMP序号

  18. #defineICMP_SEQUENCE_H_P0x28

  19. #defineICMP_SEQUENCE_L_P0x29

  20. #defineICMP_DATA_P0x2A



3.1 ICMP首部填充

ICMP首部填充需要根据协议类型填充不同的内容,对于回显请求而言只需在ICMP协议类型部分填充0即可,当然ICMP部分也包括ICMP首部校验和。


  1. voidicmp_generate_packet(BYTE*rxtx_buffer,BYTEtype)

  2. {

  3. BYTEi;

  4. WORD_BYTESck;

  5. //ICMP回显请求

  6. if(type==ICMP_TYPE_ECHOREQUEST_V)

  7. {

  8. rxtx_buffer[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V;

  9. rxtx_buffer[ICMP_CODE_P]=0;

  10. rxtx_buffer[ICMP_IDENTIFIER_H_P]=icmp_id;

  11. rxtx_buffer[ ICMP_IDENTIFIER_L_P ] = 0;

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭