LWIP網絡協議棧詳細介紹
本文的內容基本基于野火的LWIP手冊,和LWIP源碼撰寫。
網絡協議棧概述
從圖片可以看出,網絡協議棧采用分層架構,每一層都有特定的功能和協議。
TCP/IP協議分層模型
數據封裝過程
MAC數據包
我使用wireShark抓包的時候,這些MAC的前導包都是不抓的,這些應該在硬件協議上已經完成了,所以抓包抓不到。
LWIP架構詳解
LWIP (Lightweight IP) 是專為嵌入式系統設計的輕量級TCP/IP協議棧。
LWIP核心特性
// LWIP主要特性
#define LWIP_FEATURES {.memory_efficient = true, // 內存高效.cpu_efficient = true, // CPU高效 .modular_design = true, // 模塊化設計.embedded_optimized = true, // 嵌入式優化.api_multiple = true, // 多種API接口.protocols_complete = true // 完整協議支持
}// 內存使用對比
typedef struct {char name[20];uint32_t ram_usage_kb;uint32_t rom_usage_kb;
} tcp_stack_t;tcp_stack_t stacks[] = {{"LWIP", "8-40", "30-100"},{"uIP", "2-8", "10-30"},{"標準Linux", "數MB", "數MB"},{"Windows", "數十MB", "數十MB"}
};
LWIP架構組件
// LWIP核心組件架構
typedef struct lwip_core {// 網絡接口層struct netif *netif_list; // 網絡接口鏈表// 協議處理層struct {struct tcp_pcb *tcp_active_pcbs; // TCP活躍連接struct tcp_pcb *tcp_listen_pcbs; // TCP監聽連接struct udp_pcb *udp_pcbs; // UDP連接struct raw_pcb *raw_pcbs; // RAW套接字} protocol_cbs;// 內存管理struct {mem_pool_t *mem_pools; // 內存池pbuf_pool_t *pbuf_pools; // 數據包緩沖池} memory_mgmt;// 定時器系統struct {sys_timeout_t *timeouts; // 超時處理uint32_t tcp_timer_interval; // TCP定時器間隔} timer_sys;} lwip_core_t;// LWIP初始化流程
void lwip_init_sequence(void) {// 1. 內存系統初始化mem_init();memp_init();pbuf_init();// 2. 網絡接口初始化 netif_init();// 3. 協議棧初始化ip_init();tcp_init();udp_init();// 4. 應用層協議初始化dhcp_init();dns_init();printf("LWIP協議棧初始化完成\n");
}
協議層詳細分析
1. 物理層和數據鏈路層
// 以太網MAC層實現
typedef struct eth_hdr {uint8_t dest[6]; // 目標MAC地址uint8_t src[6]; // 源MAC地址 uint16_t type; // 協議類型
} __attribute__((packed)) eth_hdr_t;// 常見協議類型
#define ETHTYPE_IP 0x0800 // IPv4
#define ETHTYPE_ARP 0x0806 // ARP
#define ETHTYPE_IPV6 0x86DD // IPv6// 以太網幀處理
err_t ethernet_input(struct pbuf *p, struct netif *netif) {struct eth_hdr *ethhdr;uint16_t type;// 檢查幀長度if (p->len < sizeof(struct eth_hdr)) {pbuf_free(p);return ERR_BUF;}ethhdr = (struct eth_hdr *)p->payload;type = lwip_ntohs(ethhdr->type);// 移除以太網首部if (pbuf_header(p, -(int16_t)sizeof(struct eth_hdr))) {pbuf_free(p);return ERR_BUF;}// 根據協議類型分發switch (type) {case ETHTYPE_IP:return ip4_input(p, netif);case ETHTYPE_ARP:return etharp_input(p, netif);case ETHTYPE_IPV6:return ip6_input(p, netif);default:pbuf_free(p);return ERR_OK;}
}
2. 網絡層 (IP層)
// IP首部結構 (20字節)
typedef struct ip_hdr {uint8_t version_ihl; // 版本(4位) + 首部長度(4位)uint8_t tos; // 服務類型uint16_t len; // 總長度uint16_t id; // 標識uint16_t offset; // 標志(3位) + 片偏移(13位)uint8_t ttl; // 生存時間uint8_t proto; // 協議類型uint16_t chksum; // 首部校驗和uint32_t src; // 源IP地址uint32_t dest; // 目標IP地址
} __attribute__((packed)) ip_hdr_t;// IP協議類型
#define IP_PROTO_ICMP 1 // ICMP協議
#define IP_PROTO_TCP 6 // TCP協議
#define IP_PROTO_UDP 17 // UDP協議// IP數據包處理
err_t ip4_input(struct pbuf *p, struct netif *inp) {struct ip_hdr *iphdr;uint16_t iphdr_len;uint16_t iphdr_hlen;// 檢查IP首部iphdr = (struct ip_hdr *)p->payload;if (IPH_V(iphdr) != 4) { // 檢查IP版本pbuf_free(p);return ERR_OK;}// 獲取首部長度iphdr_hlen = IPH_HL(iphdr) * 4;if (iphdr_hlen < IP_HLEN) {pbuf_free(p);return ERR_OK;}// 校驗和檢查if (inet_chksum(iphdr, iphdr_hlen) != 0) {printf("IP校驗和錯誤\n");pbuf_free(p);return ERR_OK;}// 檢查目標地址if (!ip4_addr_isany_val(*netif_ip4_addr(inp)) &&!ip4_addr_cmp(&iphdr->dest, netif_ip4_addr(inp))) {// 不是發給本機的,丟棄或轉發pbuf_free(p);return ERR_OK;}// 移除IP首部pbuf_header(p, -(int16_t)iphdr_hlen);// 根據協議類型分發switch (IPH_PROTO(iphdr)) {case IP_PROTO_TCP:return tcp_input(p, inp);case IP_PROTO_UDP:return udp_input(p, inp);case IP_PROTO_ICMP:return icmp_input(p, inp);default:pbuf_free(p);return ERR_OK;}
}
3. 傳輸層 (TCP/UDP)
// TCP首部結構 (最小20字節)
typedef struct tcp_hdr {uint16_t src; // 源端口uint16_t dest; // 目標端口uint32_t seqno; // 序列號uint32_t ackno; // 確認號uint16_t hdrlen_rsvd_flags; // 首部長度(4位)+保留(6位)+標志(6位)uint16_t wnd; // 窗口大小uint16_t chksum; // 校驗和uint16_t urgp; // 緊急指針
} __attribute__((packed)) tcp_hdr_t;// TCP標志位
#define TCP_FIN 0x01 // 結束連接
#define TCP_SYN 0x02 // 同步序列號
#define TCP_RST 0x04 // 重置連接
#define TCP_PSH 0x08 // 推送數據
#define TCP_ACK 0x10 // 確認
#define TCP_URG 0x20 // 緊急// TCP狀態機
typedef enum {CLOSED, // 關閉狀態LISTEN, // 監聽狀態SYN_SENT, // 已發送連接請求SYN_RCVD, // 已接收連接請求ESTABLISHED, // 連接已建立FIN_WAIT_1, // 等待連接終止請求FIN_WAIT_2, // 等待連接終止CLOSE_WAIT, // 等待關閉CLOSING, // 正在關閉LAST_ACK, // 最后確認TIME_WAIT // 時間等待
} tcp_state_t;// TCP控制塊
struct tcp_pcb {ip_addr_t local_ip; // 本地IPip_addr_t remote_ip; // 遠程IPuint16_t local_port; // 本地端口uint16_t remote_port; // 遠程端口tcp_state_t state; // 連接狀態uint32_t snd_nxt; // 下一個發送序列號uint32_t snd_wl1; // 段序列號uint32_t snd_wl2; // 段確認號uint32_t snd_lbb; // 最后緩沖字節uint16_t snd_wnd; // 發送窗口uint32_t rcv_nxt; // 下一個接收序列號uint16_t rcv_wnd; // 接收窗口uint16_t rcv_ann_wnd; // 通告窗口// 重傳相關struct tcp_seg *unacked; // 未確認段struct tcp_seg *unsent; // 未發送段uint16_t rto; // 重傳超時uint8_t nrtx; // 重傳次數// 回調函數tcp_accept_fn accept; // 接受連接回調tcp_recv_fn recv; // 接收數據回調tcp_sent_fn sent; // 發送完成回調tcp_err_fn errf; // 錯誤回調
};// TCP三次握手實現
err_t tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr,uint16_t port, tcp_connected_fn connected) {// 設置遠程地址和端口ip_addr_copy(pcb->remote_ip, *ipaddr);pcb->remote_port = port;// 生成初始序列號pcb->snd_nxt = tcp_next_iss();pcb->snd_lbb = pcb->snd_nxt - 1;// 設置狀態和回調pcb->state = SYN_SENT;pcb->connected = connected;// 發送SYN段return tcp_enqueue_flags(pcb, TCP_SYN);
}
4. 應用層協議
// HTTP服務器實現示例
struct httpd_state {struct tcp_pcb *pcb;char *file;uint32_t left;uint8_t retries;
};// HTTP請求處理
err_t httpd_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) {struct httpd_state *hs = (struct httpd_state *)arg;char *data;if (err == ERR_OK && p != NULL) {// 接收HTTP請求tcp_recved(pcb, p->tot_len);data = (char *)p->payload;// 解析HTTP請求行if (strncmp(data, "GET ", 4) == 0) {char *uri = data + 4;char *space = strchr(uri, ' ');if (space) {*space = '\0';printf("HTTP GET: %s\n", uri);// 發送HTTP響應httpd_send_response(pcb, uri);}}pbuf_free(p);tcp_close(pcb);}return ERR_OK;
}// DNS客戶端實現
typedef struct dns_query {uint16_t id; // 查詢IDuint16_t flags; // 標志位uint16_t questions; // 問題數uint16_t answers; // 回答數uint16_t authority; // 權威記錄數uint16_t additional; // 附加記錄數
} __attribute__((packed)) dns_hdr_t;void dns_query(const char *hostname, dns_found_callback found, void *arg) {struct pbuf *p;struct dns_hdr *hdr;// 構造DNS查詢包p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dns_hdr) + strlen(hostname) + 2 + 4, PBUF_RAM);hdr = (struct dns_hdr *)p->payload;hdr->id = lwip_htons(dns_txid++);hdr->flags = lwip_htons(DNS_FLAG1_RD); // 遞歸查詢hdr->questions = lwip_htons(1);hdr->answers = 0;hdr->authority = 0;hdr->additional = 0;// 添加查詢域名和類型// ... 編碼域名和查詢類型 ...// 發送UDP包到DNS服務器udp_sendto(dns_pcb, p, &dns_server, DNS_SERVER_PORT);pbuf_free(p);
}
字節序處理
從圖片中可以看到字節序的重要性說明:
// 字節序轉換宏
#if BYTE_ORDER == BIG_ENDIAN
#define lwip_htons(x) (x)
#define lwip_ntohs(x) (x)
#define lwip_htonl(x) (x)
#define lwip_ntohl(x) (x)
#else
#define lwip_htons(x) ((uint16_t)((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)))
#define lwip_ntohs(x) lwip_htons(x)
#define lwip_htonl(x) ((((x) & 0xff) << 24) | \(((x) & 0xff00) << 8) | \(((x) & 0xff0000UL) >> 8) | \(((x) & 0xff000000UL) >> 24))
#define lwip_ntohl(x) lwip_htonl(x)
#endif// 字節序使用示例
void network_byte_order_example(void) {uint16_t port = 80;uint32_t ip = 0xC0A80101; // 192.168.1.1// 主機字節序 -> 網絡字節序uint16_t net_port = lwip_htons(port);uint32_t net_ip = lwip_htonl(ip);printf("主機字節序端口: %d\n", port);printf("網絡字節序端口: 0x%04X\n", net_port);printf("主機字節序IP: 0x%08X\n", ip);printf("網絡字節序IP: 0x%08X\n", net_ip);// STM32是小端模式,網絡是大端模式,需要轉換
}
LWIP內存管理
// LWIP內存池配置
#define MEM_SIZE (16*1024) // 堆內存大小
#define MEMP_NUM_PBUF 16 // pbuf數量
#define MEMP_NUM_TCP_PCB 8 // TCP PCB數量
#define MEMP_NUM_UDP_PCB 4 // UDP PCB數量
#define MEMP_NUM_TCP_SEG 16 // TCP段數量// pbuf (packet buffer) 結構
struct pbuf {struct pbuf *next; // 鏈表指針void *payload; // 數據指針uint16_t tot_len; // 總長度uint16_t len; // 當前pbuf長度uint8_t type; // pbuf類型uint8_t flags; // 標志位uint16_t ref; // 引用計數
};// pbuf內存分配
struct pbuf *pbuf_alloc(pbuf_layer layer, uint16_t length, pbuf_type type) {struct pbuf *p;uint16_t offset = 0;// 根據層計算偏移switch (layer) {case PBUF_TRANSPORT:offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;break;case PBUF_IP:offset = PBUF_LINK_HLEN + PBUF_IP_HLEN;break;case PBUF_LINK:offset = PBUF_LINK_HLEN;break;case PBUF_RAW:offset = 0;break;}// 分配內存switch (type) {case PBUF_RAM:p = (struct pbuf *)mem_malloc(sizeof(struct pbuf) + offset + length);if (p) {p->payload = (uint8_t *)p + sizeof(struct pbuf) + offset;}break;case PBUF_POOL:p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);if (p) {p->payload = (uint8_t *)p + sizeof(struct pbuf) + offset;}break;}if (p) {p->type = type;p->len = p->tot_len = length;p->next = NULL;p->ref = 1;p->flags = 0;}return p;
}
LWIP移植要點
// 1. 系統抽象層 (sys_arch.c)
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"// 信號量實現
err_t sys_sem_new(sys_sem_t *sem, uint8_t count) {*sem = xSemaphoreCreateCounting(255, count);return (*sem != NULL) ? ERR_OK : ERR_MEM;
}void sys_sem_signal(sys_sem_t *sem) {xSemaphoreGive(*sem);
}uint32_t sys_arch_sem_wait(sys_sem_t *sem, uint32_t timeout) {TickType_t start_time = xTaskGetTickCount();if (xSemaphoreTake(*sem, timeout == 0 ? portMAX_DELAY : timeout) == pdTRUE) {return (xTaskGetTickCount() - start_time) * portTICK_PERIOD_MS;}return SYS_ARCH_TIMEOUT;
}// 郵箱實現
err_t sys_mbox_new(sys_mbox_t *mbox, int size) {*mbox = xQueueCreate(size, sizeof(void *));return (*mbox != NULL) ? ERR_OK : ERR_MEM;
}void sys_mbox_post(sys_mbox_t *mbox, void *msg) {xQueueSend(*mbox, &msg, portMAX_DELAY);
}uint32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, uint32_t timeout) {TickType_t start_time = xTaskGetTickCount();if (xQueueReceive(*mbox, msg, timeout == 0 ? portMAX_DELAY : timeout) == pdTRUE) {return (xTaskGetTickCount() - start_time) * portTICK_PERIOD_MS;}return SYS_ARCH_TIMEOUT;
}// 2. 網絡接口驅動 (ethernetif.c)
err_t ethernetif_init(struct netif *netif) {// 設置網絡接口名稱netif->name[0] = 's';netif->name[1] = 't';// 設置網絡接口功能netif->output = etharp_output; // ARP輸出netif->linkoutput = low_level_output; // 底層輸出// 設置硬件地址netif->hwaddr_len = ETHARP_HWADDR_LEN;netif->hwaddr[0] = 0x02;netif->hwaddr[1] = 0x00;netif->hwaddr[2] = 0x00;netif->hwaddr[3] = 0x00;netif->hwaddr[4] = 0x00;netif->hwaddr[5] = 0x00;// 設置最大傳輸單元netif->mtu = 1500;// 設置網絡接口標志netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET;// 初始化底層硬件low_level_init(netif);return ERR_OK;
}// 底層數據發送
err_t low_level_output(struct netif *netif, struct pbuf *p) {struct pbuf *q;uint8_t *buffer = (uint8_t *)ETH_TX_BUF_BASE;uint32_t len = 0;// 復制pbuf鏈數據到發送緩沖區for (q = p; q != NULL; q = q->next) {memcpy(buffer + len, q->payload, q->len);len += q->len;}// 啟動以太網發送ETH_HandleTypeDef *heth = &EthHandle;while (HAL_ETH_TransmitFrame(heth, len) != HAL_OK) {osDelay(1);}return ERR_OK;
}// 數據接收處理
void ethernetif_input(void const *argument) {struct pbuf *p;struct netif *netif = (struct netif *)argument;while (1) {// 等待接收信號量if (osSemaphoreWait(s_xSemaphore, TIME_WAITING_FOR_INPUT) == osOK) {do {p = low_level_input(netif);if (p != NULL) {// 將數據包傳遞給協議棧if (netif->input(p, netif) != ERR_OK) {pbuf_free(p);}}} while (p != NULL);}}
}
LWIP配置選項
// lwipopts.h 主要配置選項
#ifndef LWIP_OPTS_H
#define LWIP_OPTS_H// 系統選項
#define NO_SYS 0 // 使用OS
#define LWIP_SOCKET 1 // 啟用socket API
#define LWIP_NETCONN 1 // 啟用netconn API// 內存選項
#define MEM_ALIGNMENT 4 // 內存對齊
#define MEM_SIZE (16*1024) // 堆大小
#define MEMP_NUM_PBUF 16 // pbuf池大小
#define MEMP_NUM_UDP_PCB 4 // UDP PCB數量
#define MEMP_NUM_TCP_PCB 5 // TCP PCB數量
#define MEMP_NUM_TCP_PCB_LISTEN 4 // TCP監聽PCB數量
#define MEMP_NUM_TCP_SEG 16 // TCP段數量
#define MEMP_NUM_REASSDATA 5 // IP重組數據數量
#define MEMP_NUM_FRAG_PBUF 15 // 分片pbuf數量
#define MEMP_NUM_ARP_QUEUE 30 // ARP隊列大小
#define MEMP_NUM_IGMP_GROUP 8 // IGMP組數量// ARP選項
#define LWIP_ARP 1 // 啟用ARP
#define ARP_TABLE_SIZE 10 // ARP表大小
#define ARP_QUEUEING 1 // ARP隊列// IP選項
#define IP_FORWARD 0 // 禁用IP轉發
#define IP_OPTIONS_ALLOWED 1 // 允許IP選項
#define IP_REASSEMBLY 1 // IP重組
#define IP_FRAG 1 // IP分片
#define IP_REASS_MAXAGE 3 // 重組超時
#define IP_REASS_MAX_PBUFS 10 // 重組最大pbuf數
#define IP_FRAG_USES_STATIC_BUF 0 // 分片使用動態緩沖// ICMP選項
#define LWIP_ICMP 1 // 啟用ICMP
#define ICMP_TTL 255 // ICMP TTL// DHCP選項
#define LWIP_DHCP 1 // 啟用DHCP
#define DHCP_DOES_ARP_CHECK 1 // DHCP ARP檢查// UDP選項
#define LWIP_UDP 1 // 啟用UDP
#define UDP_TTL 255 // UDP TTL// TCP選項
#define LWIP_TCP 1 // 啟用TCP
#define TCP_TTL 255 // TCP TTL
#define TCP_WND (4*TCP_MSS) // TCP窗口大小
#define TCP_MAXRTX 12 // 最大重傳次數
#define TCP_SYNMAXRTX 6 // SYN最大重傳次數
#define TCP_QUEUE_OOSEQ 1 // 亂序隊列
#define TCP_MSS 1460 // 最大段長度
#define TCP_CALCULATE_EFF_SEND_MSS 1 // 計算有效MSS
#define TCP_SND_BUF (2*TCP_MSS) // 發送緩沖區大小
#define TCP_SND_QUEUELEN (4*TCP_SND_BUF/TCP_MSS) // 發送隊列長度
#define TCP_SNDLOWAT (TCP_SND_BUF/2) // 發送低水位
#define TCP_LISTEN_BACKLOG 1 // 監聽backlog// LWIP調試選項
#define LWIP_DEBUG 1
#define ETHARP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define IGMP_DEBUG LWIP_DBG_OFF
#define INET_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define RAW_DEBUG LWIP_DBG_OFF
#define MEM_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define SYS_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define PPP_DEBUG LWIP_DBG_OFF
#define SLIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF
#define AUTOIP_DEBUG LWIP_DBG_OFF
#define SNMP_MSG_DEBUG LWIP_DBG_OFF
#define SNMP_MIB_DEBUG LWIP_DBG_OFF
#define DNS_DEBUG LWIP_DBG_OFF#endif /* LWIP_OPTS_H */
LWIP應用示例
// HTTP客戶端示例
void http_client_example(void) {struct netconn *conn;ip_addr_t server_ip;err_t err;// 創建TCP連接conn = netconn_new(NETCONN_TCP);// 設置服務器地址IP4_ADDR(&server_ip, 192, 168, 1, 100);// 連接服務器err = netconn_connect(conn, &server_ip, 80);if (err == ERR_OK) {// 發送HTTP請求char *request = "GET / HTTP/1.1\r\nHost: 192.168.1.100\r\n\r\n";netconn_write(conn, request, strlen(request), NETCONN_COPY);// 接收HTTP響應struct netbuf *buf;err = netconn_recv(conn, &buf);if (err == ERR_OK) {void *data;uint16_t len;netbuf_data(buf, &data, &len);printf("HTTP響應: %.*s\n", len, (char*)data);netbuf_delete(buf);}}// 關閉連接netconn_close(conn);netconn_delete(conn);
}// UDP服務器示例
void udp_server_example(void) {struct netconn *conn;struct netbuf *buf;ip_addr_t *addr;uint16_t port;// 創建UDP連接conn = netconn_new(NETCONN_UDP);// 綁定到本地端口netconn_bind(conn, IP_ADDR_ANY, 8080);printf("UDP服務器啟動,監聽端口8080\n");while (1) {// 接收數據if (netconn_recv(conn, &buf) == ERR_OK) {addr = netbuf_fromaddr(buf);port = netbuf_fromport(buf);void *data;uint16_t len;netbuf_data(buf, &data, &len);printf("收到來自 %s:%d 的數據: %.*s\n", ip4addr_ntoa(addr), port, len, (char*)data);// 回復數據char *reply = "UDP服務器收到";struct netbuf *reply_buf = netbuf_new();netbuf_alloc(reply_buf, strlen(reply));memcpy(netbuf_data(reply_buf, NULL, NULL), reply, strlen(reply));netconn_sendto(conn, reply_buf, addr, port);netbuf_delete(reply_buf);netbuf_delete(buf);}}
}
LWIP是一個功能強大且高效的輕量級TCP/IP協議棧,特別適合資源受限的嵌入式系統。它提供了完整的網絡協議支持,同時保持了較小的內存占用和良好的性能表現。通過合理的配置和移植,可以在各種嵌入式平臺上實現可靠的網絡通信功能。
目前打算從LWIP的內存管理,內核API線程調用,網絡層,傳輸層,應用層分別撰寫。目前僅僅作為初始起步各層的簡易介紹