uip之udp应用笔记
更新时间:2023-11-19 22:17:01 阅读量: 教育文库 文档下载
- uip udp推荐度:
- 相关推荐
千兆网项目中,移植了uip到mcu中,采用udp通信方式,主要用来做一些控制协议的处理。刚开始接手的时候,并没有做过网络方面的应用,而且对tcp/ip及udp通信又不太熟悉。好在网上有一些文档,加上仔细阅读uip_process代码,一边用抓包软件一边调试,总算把uip很好的应用了起来,而且还针对项目某些应用的特殊性,对uip源码进行了一些修改。本文前半部分对uip源码的一些重要函数进行介绍,后半部分将对修改的部分做个记录,以备往后查阅。
本次使用的 是uip-1.0,抓包软件用的Wireshark 1.6.7,这个软件真的很不错,居然支持gige vision,这点真的很意外。
一、一个完整的UDP数据报文格式
其实uip就是将你要发送到网络上的数据加上报头,好让它被成功发送到目的主机。所以我们要先搞清楚一个完整的数据报文,才能搞清楚uip到底在做些什么。
Ethernet Header:由目标mac和本机mac及type组成,共14byte,当目标mac全为ff时,表示是udp广播。Type=0x0800表示是ip。在uip中,Ethernet Header结构体定义如下:
IP Header:0x45表示version=4,header length=20byte; 0028表示ip header+udp header+user data长度为40byte;6C14为包的ID,每发一个包,这个ID会自加1。80的意义是time to live,表示这个包的存活时间,路由每转发一次,就会对它自减1。17表示通信协议类型为UDP,4a0a为ip header的校验码。再后面就是源IP和目的IP地址了。 UDP Header:0aaa表示src port为2730;0f74表示dst prot为3956;14表示udp header+user data长度为20byte,c477表示udp header的校验码,在一般的情况下,这个可以为0。
在uip中,ip header和udp header结构体定义如下:
User Data:再后面就是用户的数据了。
二、ARP数据报文格式
网络中是使用IP来标识主机的,而数据链路层的第一道关卡是MAC地址。因此IP和MAC有一张动态映射表,而这张表就是由ARP协议来建立并维护的。下面是一个ARP数据报文。
同样的,前面14byte是eth header。Hardware type对于以太网来说为0001;0800表示是IPV4;06表示MAC地址的长度;04表示IP地址的长度;0001表示是arp请求,如果是0002那就是ARP应答了。后面就是发送方的MAC地址,IP地址,接收方的MAC地址,IP地址。
在eth header中,目的MAC全是ff,则表示这是一个广播,所有网络里的主机都能收到。但只有ip地址为192.168.1.11的主机才会应答。实际上,这个ARP包的意义就是在获取IP为192.168.1.11主机的MAC地址。
网络里,如果114要与11进行通讯,但又不知道它的MAC地址,那么就发一个这样的报文,11收到后会向114发一个ARP应答,114收到应答后,会将11的MAC保存在动态映射表中。当然这个表会动态的更新,也就是说11的MAC会有一个生成时间,当超时后,就要重新建立。
以上介绍的是一种情况,还有一种情况是IP冲突的检测,这个正好本项目中用到,后面会有介绍。
三、UIP源码简介
主要介绍如下三个文件。 Uip_arp.c:arp的实现; Uip.c:uip_process实现; Tapdev.c:网卡的底层读写调用。
四、建立一个连接
uip_udp_new是用来建立一个UDP连接的,入口参数是远程的IP地址和远程的端口。uip_udp_new函数将远程ip和端口写入到uip_udp_conns数组中的某一个位置,并返回它的地址。系统中支持的最大连接数量就是这个数组的大小,可通过UIP_UDP_CONNS宏来定义它的值。
当网卡收到数据时,uip_process会遍历uip_udp_conns数组,如果当前包的目的端口与本机端口不匹配,或者远程端口与uip_udp_new中的端口不匹配,那么uip会直接丢弃这个包。
如下例,建立的是一个目的IP为255.255.255.255,目的端口为1234的连接,本地端口
号为5678。在本项目中,是用来向网络中广播设备信息。所有网络中的主机1234端口都能收到这个数据包。
五、uip主调函数
uip协议的处理都是通过主调函数来调用的,它应该被放在主程序while循环中,而用户的数据接收处理,和数据发送则是在回调函数中。
主调函数分成三个部分,第一个是检查网卡上有没有接收到数据,第二个是检查有没有用户数据需要发送,最后一个是用来维护ARP映射表的。
这里不得不提到两个时间基准:
timer_set(&periodic_timer, CLOCK_SECOND / 50); timer_set(&arp_timer, CLOCK_SECOND * 10);
一个是periodic_timer,这个为20ms,用来周期性的检查有没有用户数据需要发送。 另一个是arp_timer,用来更新ARP表,每十秒表更新一次,旧的条目会被丢弃,默认的ARP表条目生存时间是20分钟。
void process_net_data(void)
{
int i;
uip_len = tapdev_read();
if(uip_len > 0) //从网络上收到数据 {
if(BUF->type == htons(UIP_ETHTYPE_IP))
{ uip_arp_ipin(); uip_input();//接收数据处理 /* If the above function invocation resulted in data that
should be sent out on the network, the global variable uip_len is set to a value > 0. */ if(uip_len > 0) //如果有数据需要返回给主机 { uip_arp_out();
tapdev_send();
} }
else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
uip_arp_arpin();
/* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */
if(uip_len > 0) tapdev_send();
{ } }
}
else if(timer_expired(&periodic_timer)) //查询用户有没有数据主动要发送 {
timer_reset(&periodic_timer); #if 0
for(i = 0; i < UIP_CONNS; i++) { uip_periodic(i); /* If the above function invocation resulted in data that
should be sent out on the network, the global variable uip_len is set to a value > 0. */
if(uip_len > 0) { uip_arp_out();
tapdev_send(); }
}
#endif
#if 1//UIP_UDP
for(i = 0; i < UIP_UDP_CONNS; i++) //每个连接都查询一遍 { uip_udp_periodic(i);
/* If the above function invocation resulted in data that should be sent out on the network, the global variable
uip_len is set to a value > 0. */ if(uip_len > 0) //如果有用户数据要发磅 {
uip_arp_out();
tapdev_send(); } }
#endif /* UIP_UDP */
/* Call the ARP timer function every 10 seconds. */ if(timer_expired(&arp_timer)) { } } }
timer_reset(&arp_timer); uip_arp_timer();
六、uip_process
uip_process是uip的核心,用于网络协议的解析和处理,如果接收到的数据包不是发给本机的,它会把它丢弃,如果是发给本机的,则会调用回调函数去执行用户的处理。 还有,如果用户要主动发送数据,主调函数中的uip_udp_periodic(i)调用uip_process,将uip_poll置1,然后再执行回调函数,用户在回调函数中判断当uip_poll为真时,将要发送的数据写入到buf,再调用uip_send就行了。 当uip_process函数返回到主调函数中时,uip_arp_out()给数据包加上eth_header,然后由tapdev_send写入到网卡中。
下面我们再来看看uip的回调函数。 UDP应用时的回调函数是UIP_UDP_APPCALL,我们将这个宏定义为Udp_app_dispath; 该函数实现如下:
void Udp_app_dispath(void) {
if (uip_poll()){ //用户发数据的接口
if (uip_udp_conn->rport == HTONS(HOST_DISCOVER_REMOTE_PORT)){ }
…….
uip_send(…..);
else if (uip_udp_conn->rport == HTONS(GVCP_UDP_PORT)) { …….. } }
else { //接收数据处理 gvcp_CmdIn(); } }
七、利用ARP来探测IP冲突
项目中需要用到ip探测和冲突检测,上电时,设备设置一个无效ip:0.0.0.0,然后随机生成一个IP地址A,再向网络中发一个ARP广播,目的IP设为A,如果网络中A存在,则马上会收到一个ARP回应,如果没有回应,那么表示这个IP A没有被占用,设备可以使用它。 在uip.arp.c的uip_arp_arpin函数中的ARP_REPLY下添加IP判断的代码就能知道是否是冲突了。
八、建立一个远程IP和端口为NULL的连接
对于设备来说,主机的IP和端口号都是未知的,那么如果主机要向设备的指定端口1234发数据怎么办呢。
那么需要建立一个远程IP和端口都为NULL的连接,在实际中调试却发现,设备接收数据时,uip_process中有对uip_udp_conn->rport的判断,当(UDPBUF->srcport == uip_udp_conn->rport)不为真时,这个包被丢弃,于是将其改为(uip_udp_conn->rport == 0 ||
UDPBUF->srcport == uip_udp_conn->rport)就可以了。
我想这可能是uip的一个bug吧,有时候网络连接的时候,并不知道对方的端口号,那么对方要向你的端口发数据,如果不做修改,将接收不到,不过uip里有个端口监听,当有主机向这个端口发数据时,它会自动的将主机的IP和端口号填到uip_connr中,但好像不适用于udp。这里以后有空再研究。
总结
总的来说,uip还是易用的,但由于其是轻量化的tcp/ip协议栈,有些功能还不支持,比如说LLA就没有,还要到Lwip上去移值。不过对于嵌入式系统来说,还是很适用的。
正在阅读:
uip之udp应用笔记11-19
物流管理部绩效考核指标 - 图文05-24
第三章复习中心对称图形(1)03-04
深圳辖区证券公司建立健全信息隔离墙制度的指导意见110-23
那短短的84秒作文600字06-30
生日纪念文章02-14
8吨回柱绞车的设计 - 图文03-13
司马煤业有限公司35KV变电站运行规程07-12
分时成交量 见抓涨停通达信指标公式源码04-08
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 笔记
- 应用
- uip
- udp
- 九年级英语《课程纲要》
- 2012全年检修计划
- 土地利用总体规划数据库成果汇交要求-国土资源部
- 列夫托尔斯泰教案
- 美国NTRON工业交换机选型中文手册北京捷泰兴业
- 《采油工程》考试改革课堂考核环节试题第一次采油大作业答案
- 初中化学推断题100题(含答案)
- 牵手夕阳红,再进敬老院
- 全国武术套路竞赛规则
- 全国2008年10月高等教育自学考试计算机通信网试题及部分答案
- 2011年科研成果登记表
- 公司承建G318线林芝至拉萨段公路改造工程宣传教育提纲
- 壬水日干十二月令论时间吉凶
- 设计报告--018 - 同步复接器 - 分接器的FPGA设计与实现
- 2012.9传热试题1
- 中海石油建设项目现状环境影响评估报告 - 图文
- 尔雅职业规划2016期末考试答案
- 骨关节炎诊治要点及研究进展
- 儿童保健手册
- 英语2第三次作业答案