uip协议栈入门
?
uip協(xié)議棧是一個(gè)簡(jiǎn)單的嵌入式網(wǎng)絡(luò)協(xié)議棧,其不需要操作系統(tǒng)的支持,以事件驅(qū)動(dòng)的方式編程,占用的RAM以及ROM都符合嵌入式的需求,實(shí)現(xiàn)了四個(gè)基本協(xié)議 arp,ip,icmp,tcp。傳統(tǒng)的TCP/IP協(xié)議棧,比如LInux,windows上的使用的API接口是標(biāo)準(zhǔn)的socket api。由于嵌入式MCU的RAM大小和CPU性能有限,能以運(yùn)行這種套接字的API占用資源過(guò)大,使用這種基于事件驅(qū)動(dòng)方式編程的以太網(wǎng)協(xié)議棧符合嵌入式MCU的需求
uIP事件狀態(tài)機(jī)
uIP在任何事件發(fā)生時(shí),都會(huì)調(diào)用 UIP_APPCALL(),而這個(gè)函數(shù)可以被用戶重定義,然后在這個(gè)函數(shù)中處理這些事件,以下列出的是事件和對(duì)應(yīng)的測(cè)試函數(shù)
| 一個(gè)數(shù)據(jù)包到達(dá),確認(rèn)數(shù)據(jù)已經(jīng)發(fā)出 | uip_acked() |
| 應(yīng)用程序的新數(shù)據(jù)包已經(jīng)到達(dá) | uip_newdata() |
| 一個(gè)遠(yuǎn)程主機(jī)連接到監(jiān)聽(tīng)端口 | uip_connected() |
| 一個(gè)到達(dá)遠(yuǎn)程主機(jī)的連接成功建立 | uip_connected() |
| 計(jì)時(shí)時(shí)間滿需要重發(fā) | uip_rexmit() |
| 計(jì)時(shí)時(shí)間滿周期性輪詢 | uip_poll() |
| 遠(yuǎn)程主機(jī)關(guān)閉連接 | uip_closed() |
| 遠(yuǎn)程主機(jī)中斷連接 | uip_aborted() |
| 太多重傳,導(dǎo)致連接中斷 | uip_timedout() |
?
UIP協(xié)議棧的調(diào)用過(guò)程
uip_init() 初始化uip協(xié)議棧,
uip_input() 當(dāng)網(wǎng)絡(luò)設(shè)備讀到一個(gè)IP包到緩沖區(qū)
uip_periodic() 代表1s一次
uip_input() //讀一個(gè)IP包到緩沖區(qū) uip_process(UIP_DATA) //處理事件 UIP_APPCALL();//回調(diào)接口 tcp_demo_appcall //應(yīng)用程序的回調(diào)接口
tcp_demo_appcall
/TCP應(yīng)用回調(diào)接口(UIP_APPCALL) void tcp_demo_appcall(void) { switch(uip_conn->lport)//本地監(jiān)聽(tīng)端口 { case HTONS(8080): break; case HTONS(1200): break; default: break; } switch(uip_conn->rport) //遠(yuǎn)程連接服務(wù)器的80端口 { case HTONS(80): tcp_client_appcall(); break; default: break; } }
?
?
?
uip實(shí)現(xiàn)一個(gè)get請(qǐng)求 服務(wù)器 www.shilei.club
void tcp_client_appcall() { if(uip_connected())//連接上了? { // uip_send("GET / HTTP/1.1\r\nHost:www.shilei.club\r\n\r\n",48); uip_sock_flag =CLIENT_CONNECT; uip_log("tcp_client connected!\r\n");//TCP已經(jīng)連接 } if(uip_aborted())//òaía???1? { uip_sock_flag =CLIENT_DISCONNECT; uip_log("tcp_client aborted!\r\n");// tcp_client_reconnect(); } if(uip_timedout())//超時(shí) { uip_sock_flag =CLIENT_TIMEOUT; uip_log("tcp_client timeout!\r\n"); tcp_client_reconnect();//重連 } if(uip_acked())//確認(rèn)發(fā)出數(shù)據(jù) { uip_ack_flag=1; uip_log("tcp_client acked!\r\n");// } if(uip_newdata())//應(yīng)用程序的新數(shù)據(jù)包已經(jīng)到達(dá) { if(uip_ack_flag) { uip_ack_flag=0; uip_log("tcp_client recv data!\r\n");// printf("\r\n%s\r\n",uip_appdata); } } if(uip_rexmit())//需要重發(fā) { uip_log("tcp_client rexmit!\r\n"); } if(uip_poll())//應(yīng)用程序循環(huán)運(yùn)行 { if(uip_sock_flag!=CLIENT_CONNECT) { uip_abort(); } if(uip_send_flag) { uip_send_flag=0; uip_send("GET / HTTP/1.1\r\nHost:www.shilei.club\r\n\r\n",48); } } if(uip_closed())//關(guān)閉連接 { //uip_abort(); uip_sock_flag=CLIENT_DISCONNECT; uip_log("tcp_client closed!\r\n");// tcp_client_reconnect(); } }
?
?
GET請(qǐng)求的周期可以通過(guò)stm32的定時(shí)器3來(lái)控制,這里設(shè)為1S,設(shè)置發(fā)送標(biāo)志位為1,uip_poll時(shí)間發(fā)生時(shí),就會(huì)發(fā)送get請(qǐng)求
void TIM3_IRQHandler(void) { static u8 tcnt; if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) // { GPIOE->ODR ^= GPIO_Pin_8; if(uip_sock_flag == CLIENT_CONNECT)// { uip_send_flag=1; } } TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); // }
?
?
?
?
?
?
?
?
?
?
?
?
?
總結(jié)
- 上一篇: SQL数据库查询LIMIT 数据分页
- 下一篇: jenkins 命令执行 (CVE-20