uip-学习笔记(移植篇)

来源:互联网 发布:360搜索引擎推广 知乎 编辑:程序博客网 时间:2024/05/18 20:06

UIP

1、 uip_input(); 当网卡驱动收到一个包时,将包存放于全局缓冲区uip_buf中,包的大小由全局变量uip_len约束;同时将调用uip_input();该函数会根据包首部的协议处理这个包将该包发送给需要该包的应用程序;当该函数返回时,一个输出包同样放在全局缓冲区uip_buf里;大小赋给uip_len;若uip_len等于0;说明没有包要发送。否则调用系统底层的发包函数,将该包发送至网络上。

2、 uip_periodic(); uip周期计时是用于驱动所有的uip内部时钟事件。当周期计时激发,每一个TCP连接都会调用uip_periodic()函数;类似于uip_input()函数;uip_periodic()函数返回时,输出的IP包要放到uip_buf中;供底层系统查询uip_len的大小发送。

3、 由于使用TCP\IP的应用场景很多,因此应用程序作为单独的模块由用户实现。Uip协议栈提供一系列接口函数供用户程序调用,其中大部分函数有C的宏命令实现的,主要是为了速度、代码大小、效率和堆栈的使用。用户需要将应用层入口程序作为接口提供给uip协议栈,并将这个函数定义为宏UIP_APPCALL()。这样uip在接受到底层传来的数据包后,在需要送到上层应用程序处理的地方,调用UIP_APPCALL()。在不用修改协议栈的情况下可以适配不同的应用程序。

4、 Uip协议栈为我们提供了很多接口函数,这些函数在uip.h中定义,为了减少函数调用造成的额外支出,大部分接口函数是以宏命令实现的,uip提供的接口函数有:

1、 初始化uip协议栈:uip_init();
2、 处理输入包:uip_input();
3、 处理周期计时事件:uip_periodic();
4、 开始监听端口:uip_listen();
5、 连接到远程主机:uip_connect();
6、 接收到连接请求:uip_connected();
7、 主动关闭连接:uip_close();
8、 连接被关闭:uip_closed();
9、 发出去的数据被应答:uip_acked();
10、 在当前连接发送数据:uip_send();
11、 在当前连接上收到新的数据:uip_newdata();
12、 告诉对方要停止连接:uip_stop();
13、 连接被意外终止:uip_aborted();

5、 uip的移植

1、 uip1.0源码中有以下文件:apps文件夹 doc文件夹 lib文件夹 uip文件夹 unix文件夹 README.txt文件 uip-1.0-changelog.txt文件。其中apps文件夹里面是uip提供的各种参考代码,本实验,我们主要用到里面的webserver部分。Doc文件夹里面是uip的一些说明文档,是学习uip的官方资料。Lib文件夹里面是用于内存管理的一些代码,我们这里没有用到。Uip里面就是uip1.0的源码了,我们全部笑纳。Unix里面提供的是具体的应用实例,我们移植参考主要是依照这个里面的代码。
2、 移植第一步:实现在unix文件夹下tapdev.c里面的三个函数。①、首先是tapdev_init()函数,该函数用于初始化网卡(也就是我们的ENC28J60),通过这个函数实现网卡初始化。②、其次需实现的函数是tapdev_read()函数,该函数用于从网卡读取一包数据,将读取到的数据存放于全局缓存uip_buf中,数据的长度返回给uip_len;③、最后需实现的是tapdev_send()函数,该函数用于向网卡发送一包数据,将全局缓冲区uip_buf里面的数据发送出去,其实这三个函数就是实现最底层的网卡操作。
3、 移植第二步:因为uip协议栈需要使用时钟,为TCP和ARP的定时器服务,因此我们需要STM32提供一个定时器做时钟,提供10ms计时(假设clock_arch.h里面的CLOCK_CONF_SECOND为10),通过colock-arch.c里面的clock_time()函数返回给uip使用。
4、 移植第三步:配置uip-conf.h里面的宏定义选项。主要用于设置TCP最大连接数、TCP监听端口、CPU大小端模式等,这个大家根据自己需要配置即可。

6、通过以上三步的修改,我们基本上就完成了uip的移植。在使用uip的时候,一般通过如下顺序:

1、实现接口函数(回调函数)UIP_APPCALL。
该函数是我们使用uip最关键的部分,它是uip和应用程序的接口,我们必须根据自己的需要,在该函数做各种处理,而做这些处理的触发条件,就是前面第四点提到的uip提供的那些接口函数,如uip_newdata()、uip_acked()、uip_close()等等。另外,如果是UDP,那么还需要实现UIP_UDP_APPCALL回调函数。
2、调用tapdev_init()函数,先初始化网卡。
此步先初始化网卡,配置MAC地址,为uip和网络通信做好准备。
3、调用uip_init()函数,初始化uip协议栈。
此步主要用于uip自身初始化,我们直接调用就是。
4、设置IP地址、网关以及掩码
这个和电脑上网差不多,只不过我们这里是通过uip_ipaddr()、uip_sethostaddr()、uip_setdraddr()、和uip_setnetmask()等函数实现。
5、 设置监听端口
Uip根据你设定的不同监听端口,实现不同的服务,比如我们实现webserver就监听80端口(浏览器默认的端口是80端口),凡是发现80端口的数据,都通过webserverd 的APPCALL函数处理。根据自己的需要设置不同的监听端口。不过uip有本地端口(iport)和远程端口(rport)之分,如果是做服务器,我们通过监听本地客户端(iport)实现;如果是做客户端,则需要远程端口(rport)。
6、 处理uip事件
最后,uip通过uip_polling函数轮训处理uip事件。该函数必须插入到用户的主循环里面(也就是必须每隔一定时间调用一次)。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1、Clock-arch.c,属于uip协议栈,uip通过该代码里面的clock_time()函数获取时钟节拍。
2、Tapdev.c,同样是属于uip提供,用来实现uip与网卡的接口,该文件实现tapdev_init()、3、tapdev_read()、tapdev_send()三个重要函数。
4、tcp_demo.c,完成UIP_APPCALL函数函数的实现,即tcp_demo_appcall()函数。该函数根据端口的不同,分别调用不同的appcall函数,实现不同功能。同时该文件还实现了uip_log函数,用于打印日志。
5、tcp_client_demo.c,完成一个简单的TCP客户端应用,实现与电脑TCP服务端数据收发。
6、tcp_server_demo.c,完成一个简单的TCP服务端应用,实现与电脑TCP客户端的数据收发。
7、httpd.c、http-cgi.c、http-fs.c和httpd-strings.h,属于uip提供的WEB服务器参考代码,我们通过修改部分代码,实现一个简单的web服务器。

1 0