<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Network_Stack</id>
	<title>Network Stack - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.foofun.cn//index.php?action=history&amp;feed=atom&amp;title=Network_Stack"/>
	<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Network_Stack&amp;action=history"/>
	<updated>2026-04-06T02:45:51Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>http://wiki.foofun.cn//index.php?title=Network_Stack&amp;diff=701&amp;oldid=prev</id>
		<title>Zhang3：创建页面，内容为“{{In_Progress}} 本文是关于编写TCP/IP协议栈的，即使用链路层（如以太网卡）来处理IP、ARP、TCP、UDP等协议的数据包的子系统。  ==扫描PCI设备==  首先要做的是扫描安装在机器上的PCI设备，以便通过查看特定的供应商ID和设备ID来检测以太网卡。 有关更多详细信息，请参见PCI页面。  ==为NIC编写驱动程序==  找到以太网卡后，需要实…”</title>
		<link rel="alternate" type="text/html" href="http://wiki.foofun.cn//index.php?title=Network_Stack&amp;diff=701&amp;oldid=prev"/>
		<updated>2022-03-02T06:45:26Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“{{In_Progress}} 本文是关于编写TCP/IP协议栈的，即使用链路层（如以太网卡）来处理IP、&lt;a href=&quot;/index.php?title=Address_Resolution_Protocol&quot; title=&quot;Address Resolution Protocol&quot;&gt;ARP&lt;/a&gt;、TCP、UDP等协议的数据包的子系统。  ==扫描PCI设备==  首先要做的是扫描安装在机器上的PCI设备，以便通过查看特定的供应商ID和设备ID来检测以太网卡。 有关更多详细信息，请参见&lt;a href=&quot;/index.php?title=PCI&quot; title=&quot;PCI&quot;&gt;PCI&lt;/a&gt;页面。  ==为NIC编写驱动程序==  找到以太网卡后，需要实…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{In_Progress}}&lt;br /&gt;
本文是关于编写TCP/IP协议栈的，即使用链路层（如以太网卡）来处理IP、[[Address Resolution Protocol|ARP]]、TCP、UDP等协议的数据包的子系统。&lt;br /&gt;
&lt;br /&gt;
==扫描PCI设备==&lt;br /&gt;
&lt;br /&gt;
首先要做的是扫描安装在机器上的PCI设备，以便通过查看特定的供应商ID和设备ID来检测以太网卡。 有关更多详细信息，请参见[[PCI]]页面。&lt;br /&gt;
&lt;br /&gt;
==为NIC编写驱动程序==&lt;br /&gt;
&lt;br /&gt;
找到以太网卡后，需要实现一个驱动程序，使其能够发送和接收数据。 如果你使用的是仿真器，Intel E1000是一款很好的驱动程序编写卡，因为它可以在各种仿真器上使用，比如VirtualBox -  osdev.org上的这里对进行了更多介绍（请参阅[[Intel Ethernet i217]]）。 如果在实现E1000驱动程序时遇到问题，可以从[[RTL8139]]开始，这是一种更简单的旧以太网卡。&lt;br /&gt;
&lt;br /&gt;
从以太网卡出来的第一件事是机器的MAC地址。 在本地网络上交换数据需要这个6字节的地址。&lt;br /&gt;
&lt;br /&gt;
你能做的最简单的测试就是在网络上发送ARP广播。 你可以用[https://www.wireshark.org/ Wireshark]既可以捕获有效ARP请求的示例，也可以验证目标主机是否已接收到你自己的请求。 就接收数据而言，你的网卡应该捕获通过本地网络发送的数据，即使这些数据没有发送到你的机器。&lt;br /&gt;
&lt;br /&gt;
==网络协议==&lt;br /&gt;
&lt;br /&gt;
一旦你可以通过NIC发送和接收数据，并获得机器的MAC地址，你就必须实施（至少部分实施）几种相互共存的网络协议：&lt;br /&gt;
&lt;br /&gt;
* Ethernet以太网协议：这是使用MAC地址将数据发送到本地网络上另一台机器的基本协议。 这是所有其他功能的基础，因为如果你想与外界通信，你需要向路由器发送数据。&lt;br /&gt;
** [[ARP]]（Address Resolution Protocol 地址解析协议）：允许将IPv4地址转换为MAC地址&lt;br /&gt;
** IP（Internet Protocol）协议：它位于以太网之上，需要在给定IP地址的互联网上发送数据。  最常见的版本是使用32位IP地址的IPv4，但IPv6（使用128位IP地址）也正在获得越来越多的注意。 请注意，IP提供了发送数据包的“最大努力（best effort）”发送，但不能保证数据包将成功到达目的地，也不能保证数据包将按发送顺序接收&lt;br /&gt;
*** [[ICMP]]（Internet Control Message Protocol互联网控制消息协议）：由ping或traceroute等工具使用&lt;br /&gt;
*** UDP（User Datagram Protocol 用户数据报协议）：一种无连接传输协议，将源端口和目标端口的概念添加到IP中。 应用程序服务可以订阅一个或多个端口，以便在UDP消息发送到该端口时收到通知&lt;br /&gt;
**** DHCP（Dynamic Host Configuration Protocol动态主机配置协议）：允许请求机器网络配置信息，如其IP地址、本地路由器的IP地址、DNS等。&lt;br /&gt;
**** DNS（Domain Name System 域名系统）：获取给定域名的IP地址&lt;br /&gt;
***TCP（Transmission Control Protocol 传输控制协议）：与UDP一样，它添加了源端口和目标端口的概念。 然而，TCP更为复杂，因为它创建了自己的会话机制，并确保使用它的应用程序将按顺序接收数据包，如果需要，还会重新发送数据包。 &lt;br /&gt;
**** [[SSL/TLS]]（可选）：在建立安全连接时使用&lt;br /&gt;
***** HTTP（HyperText Transfer Protocol 超文本传输协议）：定义一种请求和响应机制，用于传输网页、图像和其他资源。&lt;br /&gt;
***** Telnet：使用命令行Shell远程访问机器的协议。&lt;br /&gt;
&lt;br /&gt;
[https://www.wireshark.org/ Wireshark]是可以帮助你的首选工具，它是一个免费的网络嗅探器和分析器。 因为它非常详细地解释了数据包的每个字节对应于什么，可以用来理解各种网络协议是如何编码的，。 请注意，在Windows上，Wireshark不会捕获环回（loopback）流量（即从本地主机到本地主机的流量），因此可能不会捕获模拟器和主机之间的网络流量。 但是，你可以使用Rawcap将网络流量捕获到文件中，并使用Wireshark对其进行检查。&lt;br /&gt;
&lt;br /&gt;
==网络栈==&lt;br /&gt;
&lt;br /&gt;
网络协议被组织成一个栈，每一层调用下一层。 通过网络发送的数据包将由多个报头组成，每一层对应一个报头。&lt;br /&gt;
&lt;br /&gt;
考虑DHCP请求的例子。 这是你可能希望尽早实施的协议之一，因为它允许你的机器查找其IP地址，获取本地路由器IP地址，DNS IP地址- 这样就能够获得通过网络正确通信的基本信息。&lt;br /&gt;
&lt;br /&gt;
实现这些的一种方法如下：&lt;br /&gt;
&lt;br /&gt;
* 操作系统决定发送DHCP请求，因此调用DHCP层&lt;br /&gt;
** DHCP层要求UDP层创建一个数据包，其目标是IP地址255,255,255,255（广播到整个本地网络）、端口53，有效负载大小为300字节（长度可能不同）&lt;br /&gt;
*** UDP层要求IP层创建一个UDP类型的数据包，地址为255,255,255,255，大小为308字节&lt;br /&gt;
**** IP层要求以太网层创建一个长度为328字节的IPv4类型的数据包，其目标是IP地址255,255,255,255&lt;br /&gt;
***** 以太网层创建一个大小为342字节的数据包，并在前14个字节中写入以太网报头，包括源地址（机器的MAC地址）、目标MAC地址FF:FF:FF:FF:FF:FF（从IP地址255,255,255,255翻译过来）并将其发送回IP层&lt;br /&gt;
**** IP层将IP报头写入以太网报头后的20字节中，并将其发送到UDP层&lt;br /&gt;
*** UDP层在IP报头之后的8个字节中写入报头，并将其发送到DHCP层&lt;br /&gt;
** DHCP层将其请求写入剩下的300字节，并将其发送回UDP层&lt;br /&gt;
*** UDP层通过写入校验和（包含DHCP消息）来完成报头，并将其发送到IP层&lt;br /&gt;
**** IP层将其发送到以太网层&lt;br /&gt;
***** 以太网层将数据包发送到以太网卡，以太网卡通过网络发送消息&lt;br /&gt;
&lt;br /&gt;
通过网络实际发送的数据包如下所示：&lt;br /&gt;
&lt;br /&gt;
{| {{wikitable}}&lt;br /&gt;
|-&lt;br /&gt;
|以太网报头（14字节）&lt;br /&gt;
|-&lt;br /&gt;
|IPv4报头（20字节）&lt;br /&gt;
|-&lt;br /&gt;
|UDP报头（8字节）&lt;br /&gt;
|-&lt;br /&gt;
|DHCP请求（300字节有效负载）&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
DHCP响应的格式与请求的格式相同，应按如下方式处理：&lt;br /&gt;
* 以太网卡驱动程序将验证目标MAC是当前机器的，如果是，则将数据包发送到以太网层&lt;br /&gt;
* 以太网层将查看以太网报头，检查服务类型（应该是IP），并将数据包（去掉以太网报头）发送到IP层&lt;br /&gt;
* IP层将检查IP报头，验证校验和，因为其类型是UDP，所以将数据包（不带IP报头）转发到UDP层。&lt;br /&gt;
* UDP层将检查UDP报头，验证校验和，并根据目标端口将有效负载发送到正确的服务——在本例中是DHCP层（再次剥离UDP报头）&lt;br /&gt;
* DHCP层将读取DHCP消息，验证消息类型是否为响应（即，它是来自路由器的响应），并将检索其IP地址、路由器IP地址和其他网络配置信息。&lt;br /&gt;
&lt;br /&gt;
请注意，根据定义，网络协议是异步的，即在网络上发送请求，需要等待其响应。 特别是，如果有回应，也你无法预测什么时候会有回应。 由于传入的数据包由中断处理程序处理，因此它可以随时中断你的代码。&lt;br /&gt;
&lt;br /&gt;
==小端和大端==&lt;br /&gt;
&lt;br /&gt;
按照惯例，任何在互联网上编码的消息都使用big-endian（最高有效字节排在第一位）。 对于在英特尔和AMD处理器上开发的人来说，这是一件需要时刻牢记的事情，因为x86处理器使用little endian编码数字。 因此，你必须经常转换数字。 以下两个函数用于将endian转换为16位和32位整数：&lt;br /&gt;
&lt;br /&gt;
    uint16_t switch_endian16(uint16_t nb) {&lt;br /&gt;
        return (nb&amp;gt;&amp;gt;8) | (nb&amp;lt;&amp;lt;8);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    uint_t switch_endian32(uint_t nb) {&lt;br /&gt;
        return ((nb&amp;gt;&amp;gt;24)&amp;amp;0xff)      |&lt;br /&gt;
               ((nb&amp;lt;&amp;lt;8)&amp;amp;0xff0000)   |&lt;br /&gt;
               ((nb&amp;gt;&amp;gt;8)&amp;amp;0xff00)     |&lt;br /&gt;
               ((nb&amp;lt;&amp;lt;24)&amp;amp;0xff000000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==校验和（Checksums）==&lt;br /&gt;
&lt;br /&gt;
一些网络协议使用校验和来验证消息在传输过程中是否被意外更改。 如果没有有效的校验和，数据包可能会被忽略。 校验和是一个16位数字，可以使用的计算方式如下：&lt;br /&gt;
*将消息拆分为16位的校验和块&lt;br /&gt;
* 累加那些块&lt;br /&gt;
* 如果消息的字节数为奇数，则最后一个字节应计为较高的字节，以得到一个完整16位的数字（例如，如果最后一个字节为0x42，则添加0x4200）&lt;br /&gt;
* 如果总和不适合16位数字（即大于0xFFFF），则去掉前16位并将其添加到低16位。 重复最后一步，直到得到16位和&lt;br /&gt;
* 返回该和的二进制反转&lt;br /&gt;
&lt;br /&gt;
IP校验和只覆盖它自己的报头。 UDP和TCP校验和比较复杂，因为它们包括UDP/TCP报头、有效负载（即UDP/TCP报头之后的任何内容）以及由源和目标IP地址、IP类型（0x11代表UDP，0x06代表TCP）和UDP/TCP消息长度（从UDP/TCP报头开始）组成的“伪报头”。&lt;br /&gt;
&lt;br /&gt;
正确计算校验和可能很棘手，Wireshark可以帮助你。 为此，通过进入编辑/首选项/协议，确保它正在验证校验和（默认情况下未启用该选项），选择所需的协议（例如UDP、TCP、IPv4），并确保选中“如果可能，验证校验和”。 这样，Wireshark将告诉你校验和是否有效，如果无效，其值应该是多少。&lt;br /&gt;
&lt;br /&gt;
== ARP ==&lt;br /&gt;
&lt;br /&gt;
ARP协议将是你需要实现的首批协议之一。 没有它，你将无法在本地网络上进行通信，更不用说在互联网上了。 幸运的是，这是一个简单的协议，只需要实现几个功能：&lt;br /&gt;
* 发送请求和处理回复：你的操作系统需要执行一个请求，将IP地址转换成MAC地址，这是与你的本地路由器通信所必需的。 这意味着不仅要发送一个请求包，还要在收到回复时进行处理，以便操作系统可以更新其ARP表&lt;br /&gt;
 *接收请求并发送回复：你的操作系统还需要能应答按其方式发送的请求（例如，当有人询问其MAC地址时）。 特别是，本地路由器会定期向你的机器发送ARP请求。 如果没有响应，路由器会认为你的机器坏了，不会再转发更多的流量了。&lt;br /&gt;
&lt;br /&gt;
== TCP ==&lt;br /&gt;
&lt;br /&gt;
TCP是最复杂的网络协议之一。&lt;br /&gt;
&lt;br /&gt;
首先，它在客户端和服务器之间创建了一个虚拟连接。 为了实现这一点，TCP报头包含多个标志，双方将使用这些标志来通信该连接的状态：SYN（同步 synchronize）、ACK（确认 acknowledge）、PSH（推送 Push）、FIN（完成 finish）和其他标志。&lt;br /&gt;
&lt;br /&gt;
除此之外，TCP还试图解决这样一个困境：IP不能保证数据包按发送顺序被接收，更不用说完整接收了。 这就是为什么它跟踪实际发送的数据量，要求各方定期确认他们收到的数据，并在需要时重新发送数据包的原因。 为此，TCP报头包含一个序列号和一个确认号。&lt;br /&gt;
&lt;br /&gt;
在TCP连接过程中，双方都可以互相发送一些数据，这些数据分为多个数据包。 考量当前通信到什么阶段的一种方法是发送该通信中的位置（按字节数）。 TCP数据包中的序列号（sequence number）是当前数据包所在的位置。 同样，确认号（acknowledgement number）表示一方希望另一方发送的位置（仍以字节为单位）。&lt;br /&gt;
&lt;br /&gt;
当任何一方接收到序列号为S、确认号为A、负载大小为N的TCP数据包时，其发送的下一个数据包应具有序列号A（即发送另一方期望的数据）和确认号S+N（如果N为空，则为S+1）。&lt;br /&gt;
&lt;br /&gt;
===建立连接===&lt;br /&gt;
&lt;br /&gt;
通过以下三次握手建立TCP连接：&lt;br /&gt;
* 客户端向服务器发送SYN请求（即设置了SYN标志的消息）&lt;br /&gt;
* 服务器以SYN+ACK请求进行响应（该标准还允许它分别发送ACK和SYN，尽管这种情况很少发生）。&lt;br /&gt;
* 客户端发送ACK响应。&lt;br /&gt;
&lt;br /&gt;
SYN包中使用的序列号是初始序列号； 所有进一步的数据包应使用初始序列号的增量序列号。  序列号可以通过发送带有新序列号的新SYN数据包来重置。&lt;br /&gt;
&lt;br /&gt;
初始SYN和SYN+ACK数据包“可能”还包含要发送到应用程序的数据，但很少使用。  TCP规范规定，在建立连接之前（即，在接收到最终ACK响应数据包之后），不得将该数据发送到应用程序。&lt;br /&gt;
&lt;br /&gt;
===传输数据===&lt;br /&gt;
&lt;br /&gt;
要发送数据，任何一方都可以发送PSH、ACK消息，实际数据在TCP报头之后。 另一方需要发送ACK消息以确认其已收到数据包。 如果没有，发送方将再次发送数据包。 这就是一些TCP/IP实现的不同之处 - 有些可能会在发送ACK之前等待或多或少的时间。&lt;br /&gt;
&lt;br /&gt;
===关闭连接===&lt;br /&gt;
&lt;br /&gt;
连接的终止：&lt;br /&gt;
* 想要关闭连接的一方发送一个带有FIN标志的数据包&lt;br /&gt;
* 另一方发送FIN，ACK消息&lt;br /&gt;
* 一开始主动关闭发送确认消息&lt;br /&gt;
&lt;br /&gt;
与用于建立连接的数据包一样，这些数据包不包含任何有效负载，只包含TCP报头。&lt;br /&gt;
&lt;br /&gt;
===一个例子===&lt;br /&gt;
&lt;br /&gt;
让我们来看一个HTTP GET请求的TCP通信示例：&lt;br /&gt;
&lt;br /&gt;
{| {{wikitable}}&lt;br /&gt;
|-&lt;br /&gt;
! 源-&amp;gt;目的地&lt;br /&gt;
! 目的地-&amp;gt;源&lt;br /&gt;
! 说明&lt;br /&gt;
|-&lt;br /&gt;
| Flag: SYN&lt;br /&gt;
seq_nb=0, ack_nb=0&lt;br /&gt;
|&lt;br /&gt;
|TCP握手的开始。 它正在发送字节 #0（没有有效负载的数据包将被视为至少有一个字节的通信），并且尚未从服务器接收任何数据&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| Flags: SYN, ACK&lt;br /&gt;
seq_nb=0, ack_nb=1&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| Flag: ACK&lt;br /&gt;
seq_nb=1, ack_nb=1&lt;br /&gt;
| &lt;br /&gt;
|TCP握手完成后，可以开始通信&lt;br /&gt;
|-&lt;br /&gt;
| Flags: PSH, ACK&lt;br /&gt;
seq_nb=1, ack_nb=1, len=77&lt;br /&gt;
| &lt;br /&gt;
| 这是客户端发送的HTTP GET请求。这是第一个具有实际有效载荷的数据包&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| Flag: ACK&lt;br /&gt;
seq_nb=1, ack_nb=78&lt;br /&gt;
| 服务器确认HTTP请求：它已成功读取字节#77，因此希望下一次通信从字节#78开始&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| Flags: PSH, ACK&lt;br /&gt;
seq_nb=1, ack_nb=78, len=1009&lt;br /&gt;
|这是主体的HTML&lt;br /&gt;
|-&lt;br /&gt;
| Flag: ACK&lt;br /&gt;
seq_nb=78, ack_nb=1010&lt;br /&gt;
| &lt;br /&gt;
|客户端确认服务器发送的消息：它正在发送字节#78，并且已接收到字节#1009，因此希望下一次通信从字节#1010开始&lt;br /&gt;
|-&lt;br /&gt;
| Flags: FIN, ACK&lt;br /&gt;
seq_nb=78, ack_nb=1010&lt;br /&gt;
| &lt;br /&gt;
|客户端终止TCP连接&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| Flags: FIN, ACK&lt;br /&gt;
seq_nb=1010, ack_nb=79&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| Flag: ACK&lt;br /&gt;
seq_nb=79, ack_nb=1011&lt;br /&gt;
| &lt;br /&gt;
| TCP通信的结束&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==需要关注什么==&lt;br /&gt;
协议栈的形式会因设计决策而有所不同。这些决策点可能包括&lt;br /&gt;
* 数据包是否在一个缓冲区中的处理层之间传递，或者在通过层边界时是否复制到新的缓冲区；&lt;br /&gt;
* 针对无论是入站帧还是出站帧，使用专用线程与链路层通信，该线程是都完全包含在中断处理程序中，还是单线程环境中的循环中；&lt;br /&gt;
* 帧（如以太网帧）是立即处理还是排队处理；&lt;br /&gt;
* 无论你想要TCP支持还是UDP支持，或者仅仅是IP支持；TCP是协议栈中最复杂的部分，在lwip实现中，有一半代码是特定于TCP的。&lt;br /&gt;
&lt;br /&gt;
例如，一个协议栈可能&lt;br /&gt;
* 让NIC的API提供三个功能：设置NIC、轮询帧和发送帧；&lt;br /&gt;
* 在一个线程中与NIC进行入帧和出帧通信；&lt;br /&gt;
* 在另一个线程中从接收队列解编入站帧。&lt;br /&gt;
&lt;br /&gt;
==一般考虑事项==&lt;br /&gt;
* 在以太网上编写协议栈时，你可能希望提供对ARP协议和解析功能的支持。&lt;br /&gt;
* 为了模块化，工作站的IP最好存储在nic_info结构中，而不是作为全局变量。&lt;br /&gt;
* 你也许会希望使用Wireshark或其他数据包嗅探器来检查通信和netcat，一旦你获得UDP或TCP支持，netcat将转储从操作系统发送的调试数据。 此外，在调试arp代码时，工具命令arping也很有用。 你也许需要编写一个触发器，例如，在收到ARP表示已为所选IP设置了地址时，重新启动你的网络系统。&lt;br /&gt;
* 你可以在一台计算机上使用专用以太网卡，通过交叉电缆连接到另一台计算机（哪里运行着你自制的操作系统），并使用静态IP。 其他可选的办法包括在为其提供的网络设备实现驱动程序后，在bochs或qemu下进行测试。&lt;br /&gt;
&lt;br /&gt;
==另见==&lt;br /&gt;
===文章===&lt;br /&gt;
* [[Diskless Booting|无盘启动]]&lt;br /&gt;
* [[:Category:Network_Hardware|网络硬件]]&lt;br /&gt;
&lt;br /&gt;
===论坛主题===&lt;br /&gt;
&lt;br /&gt;
===外部链接===&lt;br /&gt;
* [http://focus.ti.com/lit/an/slaa137a/slaa137a.pdf 有关嵌入式web服务器实现的详细信息，包括硬件、TCP/IP套件、TCP/IP栈及其API的概述。]&lt;br /&gt;
* [http://www.faqs.org/rfcs/rfc793.html RFC 793 - Transmission Control Protocol]&lt;br /&gt;
* [http://www.amazon.com/TCP-Illustrated-Protocols-Addison-Wesley-Professional/dp/0201633469/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1229662804&amp;amp;sr=8-1 TCP/IP Illustrated - 任何网络类型的必备书，很棒的参考书]&lt;br /&gt;
&lt;br /&gt;
许多tcp/ip协议栈都附带了它们的实现文档；读起来不错。&lt;br /&gt;
* [http://www.cs.northwestern.edu/~pdinda/minet/ Minet: A User-level TCP/IP Stack]&lt;br /&gt;
* [http://www.sics.se/~adam/uip/index.php/Main_Page uIP tiny stack for 8-bit embedded microcontrollers]&lt;br /&gt;
* [https://lwip.fandom.com/wiki/LwIP_Wiki lwIP轻量级实现]&lt;br /&gt;
&lt;br /&gt;
[[Category:Networking]]&lt;/div&gt;</summary>
		<author><name>Zhang3</name></author>
	</entry>
</feed>