開放原始碼的TCPIP協議棧--LwIP
1、BSD TCP/IP協議棧
BSD棧歷史上是其他商業棧的起點,大多數專業TCP/IP棧(VxWorks內嵌的TCP/IP 棧)是BSD棧派生的。這是因為BSD棧在BSD許可協議下提供了這些專業棧的雛形,BSD許用證允許BSD棧以修改或未修改的形式結合這些專業棧的程式碼而無須向建立者付版稅。同時,BSD也是許多TCP/IP協議中的創新(如廣域網中餓擁塞控制和避免)的開始點。
2、uC/IP
uC/IP是由Guy Lancaster編寫的一套基於uC/OS且開放原始碼的TCP/IP協議棧,亦可移植到其它作業系統,是一套完全免費的、可供研究的TCP/IP協議棧,uC/IP大部分原始碼是從公開原始碼BSD釋出站點和KA9Q(一個基於DOS單任務環境執行的TCP/IP協議棧)移植過來。uC/IP具有如下一些特點:帶身份驗證和報頭壓縮支援的PPP協議,優化的單一請求/回覆互動過程,支援IP/TCP/UDP協議,可實現的網路功能較為強大,並可裁減。 UCIP協議棧被設計為一個帶最小化使用者介面及可應用序列鏈路網路模組。根據採用CPU、編譯器和系統所需實現協議的多少,協議棧需要的程式碼容量空間在 30-60KB之間。
3、LwIP
LwIP是瑞士電腦科學院(Swedish Institute of Computer Science)的Adam Dunkels等開發的一套用於嵌入式系統的開放原始碼TCP/IP協議棧。LwIP的含義是Light Weight(輕型)IP協議,相對於uip。LwIP可以移植到作業系統上,也可以在無作業系統的情況下獨立執行。LwIP TCP/IP實現的重點是在保持TCP協議主要功能的基礎上減少對RAM的佔用,一般它只需要幾十K的RAM和40K左右的ROM就可以執行,這使 LwIP協議棧適合在低端嵌入式系統中使用。LwIP的特性如下:支援多網路介面下的IP轉發,支援ICMP協議,包括實驗性擴充套件的的UDP(使用者資料報協議),包括阻塞控制,RTT估算和快速恢復和快速轉發的TCP(傳輸控制協議),提供專門的內部回撥介面(Raw API)用於提高應用程式效能,並提供了可選擇的Berkeley介面API。
LwIP 之 原始碼目錄檔案詳解及移植說明:
https://blog.csdn.net/ZCShouCSDN/article/details/79229728
原始碼目錄檔案
目前,網路上多數文章所使用的LwIP版本為1.4.1。最新版本為2.0.3。從1.4.1到2.0.3(貌似從2.0.0開始),LwIP的原始碼有了一定的變化,甚至於原始碼的檔案結構也不一樣,內部的一些實現原始檔也被更新和替換了。其原始碼目錄結構如下所示(對於簡單的檔案以註釋的形式給出,核心原始碼下文會詳細說明):
LWIP-2.0.3
│ CHANGELOG // 版本更新記錄,從中可以看到LwIP不同版本的變化
│ COPYING
│ FILES // 其中說明了其所在目錄下的各目錄或檔案的用途。在不同的目錄下會有不同的該檔案
│ README
│ UPGRADING // 版本升級後可能出現不相容,該文件記錄了從老版本升級需要修改的地方。對於升級自己使用的LwIP版本時很有用處。
├─doc
│ │ contrib.txt // LwIP作為開源軟體,如果想要為其做貢獻,則需要遵循一定的準則,例如:提交程式碼的風格、報告Bug等。該文件給出了詳細的貢獻準則。
│ │ doxygen_docs.zip // 用doxygen生成的LwIP的配套文件
│ │ FILES // 其中說明了該目錄下的每個檔案的用途
│ │ mdns.txt // MDNS的說明文件
│ │ mqtt_client.txt
│ │ NO_SYS_SampleCode.c
│ │ ppp.txt // lwIP的PPP介面文件
│ │ rawapi.txt // 告訴讀者怎樣使用協議棧的Raw/Callback API進行程式設計
│ │ savannah.txt // 說明了如何獲取當前的開發原始碼
│ │ sys_arch.txt // 在有作業系統的移植的時候會被使用到,包含了移植說明,規定了移植者需要實現的函式、巨集定義等,後面有詳細說明。
│ └─doxygen // doxygen指令碼,主要用來維護LwIP的配套文件。對於使用LwIP來說用不到
│ │ generate.bat
│ │ generate.sh
│ │ lwip.Doxyfile
│ │ main_page.h
│ └─output
│ index.html
├─src /* 原始碼檔案部分下面獨立詳細說明 */
│ │ Filelists.mk
│ │ FILES // 主要記錄了該目錄下每個檔案、目錄的用途
│ ├─api
│ │ api_lib.c
│ │ api_msg.c
│ │ err.c
│ │ netbuf.c
│ │ netdb.c
│ │ netifapi.c
│ │ sockets.c
│ │ tcpip.c
│ ├─apps
│ │ ├─httpd
│ │ │ │ fs.c
│ │ │ │ fsdata.c
│ │ │ │ fsdata.h
│ │ │ │ httpd.c
│ │ │ │ httpd_structs.h
│ │ │ ├─fs
│ │ │ │ │ 404.html
│ │ │ │ │ index.html
│ │ │ │ └─img
│ │ │ │ sics.gif
│ │ │ └─makefsdata
│ │ │ makefsdata
│ │ │ makefsdata.c
│ │ │ readme.txt
│ │ ├─lwiperf
│ │ │ lwiperf.c
│ │ ├─mdns
│ │ │ mdns.c
│ │ ├─mqtt
│ │ │ mqtt.c
│ │ ├─netbiosns
│ │ │ netbiosns.c
│ │ ├─snmp
│ │ │ snmpv3.c
│ │ │ snmpv3_dummy.c
│ │ │ snmpv3_mbedtls.c
│ │ │ snmpv3_priv.h
│ │ │ snmp_asn1.c
│ │ │ snmp_asn1.h
│ │ │ snmp_core.c
│ │ │ snmp_core_priv.h
│ │ │ snmp_mib2.c
│ │ │ snmp_mib2_icmp.c
│ │ │ snmp_mib2_interfaces.c
│ │ │ snmp_mib2_ip.c
│ │ │ snmp_mib2_snmp.c
│ │ │ snmp_mib2_system.c
│ │ │ snmp_mib2_tcp.c
│ │ │ snmp_mib2_udp.c
│ │ │ snmp_msg.c
│ │ │ snmp_msg.h
│ │ │ snmp_netconn.c
│ │ │ snmp_pbuf_stream.c
│ │ │ snmp_pbuf_stream.h
│ │ │ snmp_raw.c
│ │ │ snmp_scalar.c
│ │ │ snmp_table.c
│ │ │ snmp_threadsync.c
│ │ │ snmp_traps.c
│ │ ├─sntp
│ │ │ sntp.c
│ │ └─tftp
│ │ tftp_server.c
│ ├─core
│ │ │ def.c
│ │ │ dns.c
│ │ │ inet_chksum.c
│ │ │ init.c
│ │ │ ip.c
│ │ │ mem.c
│ │ │ memp.c
│ │ │ netif.c
│ │ │ pbuf.c
│ │ │ raw.c
│ │ │ stats.c
│ │ │ sys.c
│ │ │ tcp.c
│ │ │ tcp_in.c
│ │ │ tcp_out.c
│ │ │ timeouts.c
│ │ │ udp.c
│ │ ├─ipv4
│ │ │ autoip.c
│ │ │ dhcp.c
│ │ │ etharp.c
│ │ │ icmp.c
│ │ │ igmp.c
│ │ │ ip4.c
│ │ │ ip4_addr.c
│ │ │ ip4_frag.c
│ │ └─ipv6
│ │ dhcp6.c
│ │ ethip6.c
│ │ icmp6.c
│ │ inet6.c
│ │ ip6.c
│ │ ip6_addr.c
│ │ ip6_frag.c
│ │ mld6.c
│ │ nd6.c
│ ├─include
│ │ ├─lwip
│ │ │ │ api.h
│ │ │ │ arch.h
│ │ │ │ autoip.h
│ │ │ │ debug.h
│ │ │ │ def.h
│ │ │ │ dhcp.h
│ │ │ │ dhcp6.h
│ │ │ │ dns.h
│ │ │ │ err.h
│ │ │ │ errno.h
│ │ │ │ etharp.h
│ │ │ │ ethip6.h
│ │ │ │ icmp.h
│ │ │ │ icmp6.h
│ │ │ │ igmp.h
│ │ │ │ inet.h
│ │ │ │ inet_chksum.h
│ │ │ │ init.h
│ │ │ │ ip.h
│ │ │ │ ip4.h
│ │ │ │ ip4_addr.h
│ │ │ │ ip4_frag.h
│ │ │ │ ip6.h
│ │ │ │ ip6_addr.h
│ │ │ │ ip6_frag.h
│ │ │ │ ip_addr.h
│ │ │ │ mem.h
│ │ │ │ memp.h
│ │ │ │ mld6.h
│ │ │ │ nd6.h
│ │ │ │ netbuf.h
│ │ │ │ netdb.h
│ │ │ │ netif.h
│ │ │ │ netifapi.h
│ │ │ │ opt.h
│ │ │ │ pbuf.h
│ │ │ │ raw.h
│ │ │ │ sio.h
│ │ │ │ snmp.h
│ │ │ │ sockets.h
│ │ │ │ stats.h
│ │ │ │ sys.h
│ │ │ │ tcp.h
│ │ │ │ tcpip.h
│ │ │ │ timeouts.h
│ │ │ │ udp.h
│ │ │ ├─apps
│ │ │ │ FILES
│ │ │ │ fs.h
│ │ │ │ httpd.h
│ │ │ │ httpd_opts.h
│ │ │ │ lwiperf.h
│ │ │ │ mdns.h
│ │ │ │ mdns_opts.h
│ │ │ │ mdns_priv.h
│ │ │ │ mqtt.h
│ │ │ │ mqtt_opts.h
│ │ │ │ netbiosns.h
│ │ │ │ netbiosns_opts.h
│ │ │ │ snmp.h
│ │ │ │ snmpv3.h
│ │ │ │ snmp_core.h
│ │ │ │ snmp_mib2.h
│ │ │ │ snmp_opts.h
│ │ │ │ snmp_scalar.h
│ │ │ │ snmp_table.h
│ │ │ │ snmp_threadsync.h
│ │ │ │ sntp.h
│ │ │ │ sntp_opts.h
│ │ │ │ tftp_opts.h
│ │ │ │ tftp_server.h
│ │ │ ├─priv
│ │ │ │ api_msg.h
│ │ │ │ memp_priv.h
│ │ │ │ memp_std.h
│ │ │ │ nd6_priv.h
│ │ │ │ tcpip_priv.h
│ │ │ │ tcp_priv.h
│ │ │ └─prot
│ │ │ autoip.h
│ │ │ dhcp.h
│ │ │ dns.h
│ │ │ etharp.h
│ │ │ ethernet.h
│ │ │ icmp.h
│ │ │ icmp6.h
│ │ │ igmp.h
│ │ │ ip.h
│ │ │ ip4.h
│ │ │ ip6.h
│ │ │ mld6.h
│ │ │ nd6.h
│ │ │ tcp.h
│ │ │ udp.h
│ │ ├─netif
│ │ │ │ etharp.h
│ │ │ │ ethernet.h
│ │ │ │ lowpan6.h
│ │ │ │ lowpan6_opts.h
│ │ │ │ slipif.h
│ │ │ └─ppp
│ │ │ │ ccp.h
│ │ │ │ chap-md5.h
│ │ │ │ chap-new.h
│ │ │ │ chap_ms.h
│ │ │ │ eap.h
│ │ │ │ ecp.h
│ │ │ │ eui64.h
│ │ │ │ fsm.h
│ │ │ │ ipcp.h
│ │ │ │ ipv6cp.h
│ │ │ │ lcp.h
│ │ │ │ magic.h
│ │ │ │ mppe.h
│ │ │ │ ppp.h
│ │ │ │ pppapi.h
│ │ │ │ pppcrypt.h
│ │ │ │ pppdebug.h
│ │ │ │ pppoe.h
│ │ │ │ pppol2tp.h
│ │ │ │ pppos.h
│ │ │ │ ppp_impl.h
│ │ │ │ ppp_opts.h
│ │ │ │ upap.h
│ │ │ │ vj.h
│ │ │ └─polarssl
│ │ │ arc4.h
│ │ │ des.h
│ │ │ md4.h
│ │ │ md5.h
│ │ │ sha1.h
│ │ └─posix
│ │ │ errno.h
│ │ │ netdb.h
│ │ └─sys
│ │ socket.h
│ └─netif
│ │ ethernet.c
│ │ ethernetif.c
│ │ FILES
│ │ lowpan6.c
│ │ slipif.c
│ └─ppp
│ │ auth.c
│ │ ccp.c
│ │ chap-md5.c
│ │ chap-new.c
│ │ chap_ms.c
│ │ demand.c
│ │ eap.c
│ │ ecp.c
│ │ eui64.c
│ │ fsm.c
│ │ ipcp.c
│ │ ipv6cp.c
│ │ lcp.c
│ │ magic.c
│ │ mppe.c
│ │ multilink.c
│ │ ppp.c
│ │ pppapi.c
│ │ pppcrypt.c
│ │ PPPD_FOLLOWUP
│ │ pppoe.c
│ │ pppol2tp.c
│ │ pppos.c
│ │ upap.c
│ │ utils.c
│ │ vj.c
│ └─polarssl
│ arc4.c
│ des.c
│ md4.c
│ md5.c
│ README
│ sha1.c
└─test // 一些協議棧核心測試程式.在實際使用時一般用不到!可直接刪除。
├─fuzz
│ │ config.h
│ │ fuzz.c
│ │ lwipopts.h
│ │ Makefile
│ │ output_to_pcap.sh
│ │ README
│ └─inputs
│ ├─arp
│ │ arp_req.bin
│ ├─icmp
│ │ icmp_ping.bin
│ ├─ipv6
│ │ neighbor_solicitation.bin
│ │ router_adv.bin
│ ├─tcp
│ │ tcp_syn.bin
│ └─udp
│ udp_port_5000.bin
└─unit
│ lwipopts.h
│ lwip_check.h
│ lwip_unittests.c
├─core
│ test_mem.c
│ test_mem.h
│ test_pbuf.c
│ test_pbuf.h
├─dhcp
│ test_dhcp.c
│ test_dhcp.h
├─etharp
│ test_etharp.c
│ test_etharp.h
├─ip4
│ test_ip4.c
│ test_ip4.h
├─mdns
│ test_mdns.c
│ test_mdns.h
├─tcp
│ tcp_helper.c
│ tcp_helper.h
│ test_tcp.c
│ test_tcp.h
│ test_tcp_oos.c
│ test_tcp_oos.h
└─udp
test_udp.c
test_udp.h
1
在LwIP的原始碼包中,一共包含三個目錄:doc、src、test。分別對應:原始碼的文件、原始碼、測試程式碼。最新版的原始碼與早期原始碼在某些目錄檔案是有區別的。以下主要說明src即:原始碼部分。
api目錄
LwIP提供了兩種型別的API: Callback-style APIs和Sequential-style APIs 。其中,Callback-style APIs即為LwIP最底層的介面,被稱為Raw API或者Native API;而Sequential-style APIs主要是對底層介面進行了封裝,主要包含:Netconn API、NETIF API和Socket API。在實際使用中,使用者可以任選一種API來使用。
api目錄下主要包含對底層API(raw API)封裝後的高階API的程式碼。 如果直接使用底層的的Raw API,則不需要該目錄下的檔案。而封裝後的高級別的這兩種API實現的原理都是通過引進郵箱和訊號量等通訊與同步機制,來實現對核心中***Raw API(native API)***函式的封裝和呼叫。要使用這兩種型別的API,需要底層作業系統的支援。
Raw API:(有時稱為native API)是一個設計用於在沒有作業系統時,實現零拷貝傳送和接收的事件驅動的API。 這個API也被核心堆疊用於各種協議之間的互動。 這是在沒有作業系統的情況下,執行lwIP時唯一可用的API。
因為Callback/Raw API是協議棧提供的三種程式設計介面中最複雜的一種, 它通過直接與協議棧內 核函式互動以實現程式設計,所以整個過程比較複雜。原始碼的doc目錄下有一個專門的文件:rawapi.txt說明了具體如何使用Raw API。
**Netconn API:**為普通的、順序的程式提供了使用lwIP棧的方法。 執行緒安全,僅從非TCPIP執行緒呼叫。 基於網路緩衝區(包含資料包緩衝區(PBUF))的TX / RX處理,以避免複製資料。這與BSD Socket API非常相似。 執行模型基於 開啟-讀取-寫入-關閉 範例。 由於TCP / IP堆疊本質上是事件,所以TCP / IP程式碼和應用程式必須駐留在不同的執行上下文(執行緒)中。
**Socket API:**它是建立在Netconn API之上的。其主要是由於BSD Socket API是網路通訊的一個實現。執行緒安全,僅從非TCPIP執行緒呼叫。BSD Socket API已經是網路套接字的事實上的抽象標準。目前,所有主流作業系統均實現了BSD Socket API。出於此,LwIP也提供了一套BSD Socket API。但是,標準 socket 庫中的部分函式仍無法直接通過封裝 Netconn API 來實現,因此 LwIP 中提供的socket 函式並不完整,使用者最好不要使用它進行實際應用程式開發。對應檔案為posix/sys/socket.h。
以下為每個檔案的具體說明:
api_lib.c: 包含 對外提供的 sequential API 函式的實現。函式名均以netconn_開頭。主要分為三組API:同時可用於TCP和UDP的API、只能用於TCP的API、只能用於UDP的API。
api_msg.c: 包含sequential API內部自己呼叫的函式的實現。主要包含API訊息的封裝和處理函式
err.c: 錯誤管理模組
netbuf.c: 包含了上層資料包管理函式的實現。應用程式描述待發送資料和已接收資料的基本結構。該結構只是對核心 pbuf 的簡單封裝,避免了資料的拷貝。緩衝區不能在多個執行緒之間共享。
netdb.c: 包含與主機名字轉換相關的函式,主要在 socket 中被使用到
netifapi.c: 包含了上層網路介面管理函式的實現
sockets.c: 包含了 Socket API 函式的實現
tcpip.c: 包含了上層 API 與協議棧核心互動的函式,它是整個上層 API 功能得以實現的一個樞紐,其實現的功能可以簡單理解為:從 API 函式處接收訊息,然後將訊息遞交給核心函式,核心函式根據訊息做出相應的處理。
apps目錄
使用lwIP低階raw API編寫的高層應用程式。
core目錄
TCP / IP協議棧的核心部分。主要包含協議實現、記憶體和緩衝區管理以及底層raw API的實現。它包含了IP、ICMP、IGMP、TCP、UDP 等核 心協議以及建立在它們基礎上的DNS、DHCP、SNMP 等上層應用協議。核心原始碼可以單獨執行,且不需要作業系統的支援。即:直接使用raw API程式設計。
---------------------
作者:ZCShouCSDN
來源:CSDN
原文:https://blog.csdn.net/ZCShouCSDN/article/details/79229728
版權宣告:本文為博主原創文章,轉載請附上博文連結!