uip协议栈入门
?
uip協議棧是一個簡單的嵌入式網絡協議棧,其不需要操作系統的支持,以事件驅動的方式編程,占用的RAM以及ROM都符合嵌入式的需求,實現了四個基本協議 arp,ip,icmp,tcp。傳統的TCP/IP協議棧,比如LInux,windows上的使用的API接口是標準的socket api。由于嵌入式MCU的RAM大小和CPU性能有限,能以運行這種套接字的API占用資源過大,使用這種基于事件驅動方式編程的以太網協議棧符合嵌入式MCU的需求
uIP事件狀態機
uIP在任何事件發生時,都會調用 UIP_APPCALL(),而這個函數可以被用戶重定義,然后在這個函數中處理這些事件,以下列出的是事件和對應的測試函數
| 一個數據包到達,確認數據已經發出 | uip_acked() | 
| 應用程序的新數據包已經到達 | uip_newdata() | 
| 一個遠程主機連接到監聽端口 | uip_connected() | 
| 一個到達遠程主機的連接成功建立 | uip_connected() | 
| 計時時間滿需要重發 | uip_rexmit() | 
| 計時時間滿周期性輪詢 | uip_poll() | 
| 遠程主機關閉連接 | uip_closed() | 
| 遠程主機中斷連接 | uip_aborted() | 
| 太多重傳,導致連接中斷 | uip_timedout() | 
?
UIP協議棧的調用過程
uip_init() 初始化uip協議棧,
uip_input() 當網絡設備讀到一個IP包到緩沖區
uip_periodic() 代表1s一次
uip_input() //讀一個IP包到緩沖區 uip_process(UIP_DATA) //處理事件 UIP_APPCALL();//回調接口 tcp_demo_appcall //應用程序的回調接口
tcp_demo_appcall
/TCP應用回調接口(UIP_APPCALL) void tcp_demo_appcall(void) { switch(uip_conn->lport)//本地監聽端口 { case HTONS(8080): break; case HTONS(1200): break; default: break; } switch(uip_conn->rport) //遠程連接服務器的80端口 { case HTONS(80): tcp_client_appcall(); break; default: break; } }
?
?
?
uip實現一個get請求 服務器 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已經連接 } if(uip_aborted())//òaía???1? { uip_sock_flag =CLIENT_DISCONNECT; uip_log("tcp_client aborted!\r\n");// tcp_client_reconnect(); } if(uip_timedout())//超時 { uip_sock_flag =CLIENT_TIMEOUT; uip_log("tcp_client timeout!\r\n"); tcp_client_reconnect();//重連 } if(uip_acked())//確認發出數據 { uip_ack_flag=1; uip_log("tcp_client acked!\r\n");// } if(uip_newdata())//應用程序的新數據包已經到達 { 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())//需要重發 { uip_log("tcp_client rexmit!\r\n"); } if(uip_poll())//應用程序循環運行 { 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())//關閉連接 { //uip_abort(); uip_sock_flag=CLIENT_DISCONNECT; uip_log("tcp_client closed!\r\n");// tcp_client_reconnect(); } }
?
?
GET請求的周期可以通過stm32的定時器3來控制,這里設為1S,設置發送標志位為1,uip_poll時間發生時,就會發送get請求
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 ); // }
?
?
?
?
?
?
?
?
?
?
?
?
?
總結
 
                            
                        - 上一篇: SQL数据库查询LIMIT 数据分页
- 下一篇: jenkins 命令执行 (CVE-20
