Lwip深度閱讀-網絡架構

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線程調用,網絡層,傳輸層,應用層分別撰寫。目前僅僅作為初始起步各層的簡易介紹

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/92646.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/92646.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/92646.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

嵌入式系統學習Day16(C語言中的位運算)

位運算二進制位的運算嵌入式:通過位運算 控制 硬件運算: 運算規則 & 與 一假則假 | 或 一真則真 ~ 非 真假相對 ^ 異或 相同為假 不同為真 << 左移 表示二進制位的移動 >> 右移 eg:int a 0x55; int b 0x33;0101 0101 //0x55 &am…

Endnote下載,導入曼大 harvard_manchester格式

下載endnote 并激活中國農業科技文獻與信息服務平臺&#xff0c;點擊下載 下載harvard_manchester 格式 Harvard Manchester - Referencing guide at the University of Manchester - Subject guides at University of Manchester 雙擊打開第二步下載的安裝包&#xff08;使用…

【Docker進階實戰】從多容器編排到集群部署

Docker進階實戰&#xff1a;從多容器編排到集群部署 當你已經熟悉Docker的基本操作后&#xff0c;面對的下一個挑戰往往是&#xff1a;如何管理多個容器的協作&#xff1f;如何實現容器的集群化部署與擴展&#xff1f;如何保證服務的高可用&#xff1f; 一、Docker Compose&…

【Linux文件操作】文件操作系統調用

目錄 一、文件創建&#xff08;creat 系統調用&#xff09;? 1.1 函數原型 1.2 參數說明? 1.3 返回值? 1.4 使用示例 二、文件打開&#xff08;open 系統調用&#xff09;? 2.1 函數原型 2.2 參數說明? 2.3 返回值? 2.4 使用示例 三、文件讀寫&#xff08;read 和 write …

FreeRTOS源碼分析六:vTaskDelay vs xTaskDelayUntil任務延時

系列文章目錄 FreeRTOS源碼分析一&#xff1a;task創建&#xff08;RISCV架構&#xff09; FreeRTOS源碼分析二&#xff1a;task啟動&#xff08;RISCV架構&#xff09; FreeRTOS源碼分析三&#xff1a;列表數據結構 FreeRTOS源碼分析四&#xff1a;時鐘中斷處理響應流程 Free…

Linux學習-應用軟件編程(fread/fwrite,流定義相關接口)

freadsize_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 功能按塊從文件讀取數據&#xff0c;從文件中讀 nmemb 個、每個 size 字節的元素&#xff0c;存入 ptr 指向的內存。參數- ptr &#xff1a;存儲讀取數據的內存首地址&#xff08;需提前分配足夠…

IP分片(IP Fragmentation)

目錄 一、核心概念:MTU與分片的必要性 二、IP分片的關鍵字段(IPv4頭部) 三、分片與重組流程 1. 分片過程(發送端或中間路由器) 2. 重組過程(接收端) 四、IPv4與IPv6分片的差異 五、分片的潛在問題與風險 六、總結 一、傳輸效率降低,帶寬開銷增加 二、可靠性降低,數據丟…

高并發內存池 內存釋放回收(6)

文章目錄前言一、threadcache回收內存二、centralcache回收內存三、pagecache回收內存總結前言 Hello&#xff0c;我們繼續乘勝追擊 ??本篇難度較大&#xff0c;大家要好好學一下 一、threadcache回收內存 當某個線程申請的對象不用了&#xff0c;可以將其釋放給 thread cac…

2438. 二的冪數組中查詢范圍內的乘積

2438. 二的冪數組中查詢范圍內的乘積 初始理解題目 首先&#xff0c;我們需要清楚地理解題目在說什么。題目給出一個正整數 n&#xff0c;要求我們構造一個數組 powers&#xff0c;這個數組滿足以下條件&#xff1a; 元素性質?&#xff1a;數組中的每個元素都是 2 的冪。即…

【PyTorch學習筆記 - 01】 Tensors(張量)

最近項目需要優化一下目標檢測網絡&#xff0c;在這個過程中發現還是得增加對框架底層的掌握才可行。于是準備對pytorch的一些基本概念做一些再理解。參考PyTorch的wiki&#xff0c;對自己的學習過程做個記錄。 Tensors 是一種特殊的數據結構&#xff0c;與數組和矩陣非常相似…

【C/C++】(struct test*)0->b 講解

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 一、什么是結構體成員的偏移量&#xff1f; 二、為什么需要計算偏移量&#xff1f; 三、如何計算偏移量&#xff1f; 四、總結 一、什么是結構體成員的偏移量&#…

使用Pytest進行接口自動化測試(三)

&#xff08;一&#xff09;YAML 之前在項目中&#xff0c;我們也是用過YAML來做配置文件&#xff0c;他用于以人類可讀的形式存儲信息&#xff0c; 特點: 一種簡易的可讀語言&#xff0c;用于人和計算機交換數據 通常用來存儲配置信息 跟python類似&…

算法訓練營day46 647. 回文子串、516.最長回文子序列、動態規劃總結篇

今天是動態規劃的最后一篇內容了&#xff0c;本篇主要是針對回文字符串這種“與眾不同”的遞推規律來進行講解 647. 回文子串 統計并返回這個字符串中 回文子串 的數目 暴力解法 兩層for循環&#xff0c;遍歷區間起始位置和終止位置&#xff0c;然后還需要一層遍歷判斷這個區…

Qt界面優化

1.QSS在網頁前端開發領域中&#xff0c;CSS 是一個至關重要的部分&#xff0c;描述了一個網頁的 “樣式”&#xff0c;從而起到對網頁美化的作用。所謂樣式&#xff0c;包括不限于大小、位置、顏色、背景、間距、字體等等。網頁開發作為 GUI 的典型代表&#xff0c;也對于其他客…

week1+2+3

408 計組 1.基本組成2.數據的表示和運算定點數&#xff1a;把數字分為定點整數和定點小數分開存儲 浮點數&#xff1a;用科學計數法存儲 原碼 -全部取反-> 反碼 反碼 1->補碼 補碼 -符號位取反->移碼帶余除法&#xff1a;設x,m∈Z&#xff0c;m>0則存在唯一的整數q…

java8中javafx包缺少報錯

今天拉取一個jdk1.8的項目里面有一個代碼用到了javafx&#xff0c;這個我記得是jdk中的包&#xff0c;正常不應該報錯的。然后發現jdk中還真沒有&#xff0c;查了一下是因為版本問題。 Java 8 及之前&#xff1a;Oracle JDK 自帶 JavaFX&#xff0c;OpenJDK 通常不包含Java 9 …

day072-代碼檢查工具-Sonar與maven私服-Nexus

文章目錄0. 老男孩思想-選對池塘釣美人魚1. 代碼回滾方案2. SonarQube2.1 代碼檢查工具2.2 部署sonarqube2.2.1 軟件要求2.2.2 安裝軟件2.2.3 啟動sonar2.2.4 部署插件2.3 sonar檢查java代碼2.3.1 創建sona項目2.3.2 分析java代碼2.3.3 Jenkins結合sonar檢查代碼2.4 sonar檢查非…

【前端基礎】15、列表元素、表格元素、表單元素(注:極其粗略的記載。)

一、列表元素 1、什么是列表元素2、有序列表&#xff08;ol、li&#xff09; ol有序列表 直接子元素只能是li。 li列表中的每一項。3、無序列表&#xff08;ul、li&#xff09; ol無序列表 直接子元素只能是li。 li列表中的每一項。4、定義列表&#xff08;dl、dt、dd&#xff…

IRFBG30PBF Vishay威世MOSFET場效應管

IRFBG30PBF Vishay威世&#xff1a;超快MOSFET 場效應管一、產品定位IRFBG30PBF 是Vishay威世推出的600V/30A N溝道功率MOSFET&#xff0c;采用第五代TrenchFET技術&#xff0c;專為開關電源、電機驅動、新能源逆變器等高功率場景設計。以85mΩ超低導通電阻和超快反向恢復&…

【07-AGI的討論】

AI ANI&#xff1a;artificial narrow intelligence; 如 智能音箱&#xff1b;自動駕駛汽車&#xff0c;網絡搜索&#xff0c;其他用于專業特定事項的工具&#xff1b; AGI&#xff1a;artificial general intelligence; building AI systems that could do anything a typical…