UIP 學習總結一
UIP是用C語言寫的一個網絡協議棧,UIP協議棧是TCP/IP協議棧的一個功能子集,它只能實現一次處理一個單獨的網絡接口,它支持IP、ICMP、UDP和TCP協議。UIP是一個非常精簡的協議棧,適用於8位和16位微處理器構建基於以太網的應用。本文主要總結UIP的使用,對UIP源碼的解析留待以後詳細講解。
一、獲得UIP
CSDN上可以下載UIP協議棧,以及相應的文檔資料。
二、 UIP組成結構
這裏將要講述下載後的UIP協議棧主要文件的作用。下載後的目錄結構如下
其中uip文件時整個UIP協議棧文件,不需要更改。My_arch文件夾是移植相關的文件,在移植到具體的處理器平臺時需要更改一些文件。
其中需要修改的文件有tapdev.h tapdec.c clock-arch.c clock-arch.huip_arch.c
Uip-conf.h。
Tapdev.c是關於所移植平臺上對以太網的設備接口支持,需要提供以太網的初始化和讀取網幀和發送網絡幀的函數實現。
Clock-arch.c是uip的時鐘支持,需要實現的函數有時鐘初始化,獲得時鐘函數,一般情況下會使用系統時鐘也可以用定時器提供時鐘支持。主要在移植uc/os-ii時我們一般已經使用了系統時鐘,那麼爲uip提供時鐘支持的可以使用定時器完成,也可以使用UCOS的獲得時鐘節拍的函數。
Main.c是一個使用範例,下面將詳細講解這個文件。
三、 Main.c
Main.c主要包含有循環時鐘的設置與初始化、arp時鐘的初始化、以太網設備接口初始化、uip協議棧的初始化、設定本機的IP地址 網關和掩碼、應用初始化
文件中包含以下函數調用
timer_set(&periodic_timer, CLOCK_SECOND / 2);//初始化輪詢時鐘,
timer_set(&arp_timer, CLOCK_SECOND * 10);//初始化arp時鐘
tapdev_init();//以太網設備初始化
uip_init();//UIP協議棧初始化
uip_ipaddr(ipaddr, 192,168,0,2);
uip_sethostaddr(ipaddr);//主機IP
uip_ipaddr(ipaddr, 192,168,0,1);
uip_setdraddr(ipaddr);//網關
uip_ipaddr(ipaddr, 255,255,255,0);
uip_setnetmask(ipaddr);//掩碼
httpd_init();//應用初始化,範例爲一個web服務器
main.c中最重要的是一個循環,該循環查看網絡上是否有到本機的數據幀以及本機是否有數據幀需要發送,爲UIP提供了底層設備的支持。
while(1) {
uip_len = tapdev_read();//讀取網絡幀,返回長度,數據保存在uip_buf中
//大於0則說明有網絡數據到來
if(uip_len > 0) {
//該數據類型爲 IP包
if(BUF->type == htons(UIP_ETHTYPE_IP)) {
//通知ARP有IP包進來 進行ip 對mac地址轉換並保存在arp緩存中
uip_arp_ipin();
uip_input();//調用uip_input函數對網絡數據處理
/* Ifthe above function invocation resulted in data that
should be sent out on the network, theglobal variable
uip_len is set to a value > 0. */
if(uip_len> 0) {
uip_arp_out();//如果沒有該ip的mac地址則要發送arp請求,所以在UDP應用中需要發送一次僞數據來獲得mac地址
tapdev_send();//發送數據
}
} else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
uip_arp_arpin();//arp請求
/* Ifthe above function invocation resulted in data that
should be sent out on the network, theglobal variable
uip_len is set to a value > 0. */
if(uip_len> 0) {
tapdev_send();//arp回覆
}
}
//超時則啓動輪詢
}else if(timer_expired(&periodic_timer)) {
timer_reset(&periodic_timer);
//遍歷所有的TCP鏈接
for(i = 0; i < UIP_CONNS; i++) {
uip_periodic(i);
/* Ifthe above function invocation resulted in data that
should be sent out on the network, the globalvariable
uip_len is set to a value > 0. */
if(uip_len> 0) {
uip_arp_out();
tapdev_send();
}
}
#if UIP_UDP
for(i = 0; i < UIP_UDP_CONNS; i++) {
uip_udp_periodic(i);
/* Ifthe above function invocation resulted in data that
should be sent out on the network, theglobal 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();
}
}
}
return 0;
}
該循環是UIP協議棧的的基本需要重點理解。
四 、uip-conf.h
該文件爲對UIP的配置文件。
主要配置選項有:uip TCP最大鏈接數、uip 最大監聽端口數、uip緩存大小、uip數據順序(是否顛覆)
UDP支持、UDP最大鏈接數。
其中和應用聯繫最爲直接和緊密的是UIP_APPCALL 配置和 UIP_UDP_APPCALL
這兩個宏分別需要指向uip回調的應用函數。
通常會如下配置
對於TCP應用
typedef struct { //…..成員} uip_tcp_appstate_t;//該結構體作爲uip爲每個鏈接保留的應用數據。
#ifndef UIP_APPCALL
#define UIP_APPCALLTcpApp//TcpApp是一個函數的名稱,該函數與處理TCP相關
對於UDP應用
typedef struct {//….成員} uip_udp_appstate_t;
#ifndef UIP_UDP_APPCALL
#defineUIP_UDP_APPCALL UDPApp//UDPApp爲函數名稱,該函數與處理UDP相關
五、編寫基於UIP的網絡應用。
完成以上的工作後,就可以開始編寫基於UIP的網絡應用了。
具體的編寫方法在uip文檔中有詳細的講解,這裏不多說了,主要注意一下幾點。
1、 首先要區分不同的應用,爲不同的應用分配不同的端口,然後再編寫uip回調函數時先寫
switch(uip_udp_conn->lport){
case HTONS(PORT) :
{
If(uip_newdata())
{
}else if(uip_poll())
{
}
//……其他情況分支
}
}
對於TCP應用類似。
UIP當前的TCP鏈接保存在uip_conn,UDP鏈接保存在uip_udp_conn結構體中。可以根據自己的需要靈活地設計回調函數。
2、 在加入實時操作系統支持後,在上面提及的循環中必須調用系統的延時函數,爲其他的任務提供時間運行。
3、 UIP主要是爲支持TCP協議而編寫的,對於UDP的支持不是很充分,比如它無法實現服務器端的功能而需要對UIP協議棧進行一定的修改,這個在網上有一些資料講解了,大家可以自己查詢一下。
六 小結。
第一次寫技術總結,很多方面經驗不足,還望各位提提意見,多謝大家。在總結的時候才發現自己在很多地方還是理解的模糊不清的,這也是我開始堅持寫總結的一個原因。這是對UIP的第一份總結,後面會有更加詳細地分析和總結。2013了,大家都在努力,我也要,希望我找份好工作嘞,祝福我吧,新年快樂。