文章目录
- LWIP是什么
- 基础知识
- OSI七层模型
- TCP/IP五层模型
- LwIP的模型
- 常见协议
- ARP协议
- ICMP协议
- DHCP协议
- DNS协议
- LwIP API
- Socket
- 大端模式与小端模式
- 地址字节序
- IP地址转换
- 网络并发
LWIP是什么
LWIP是一个轻量级的TCP/IP协议栈,其全称为Lightweight IP,它专门为小型嵌入式系统设计,具有占用资源少、易于移植、可裁剪性高等特点。
LWIP的设计目的是为嵌入式设备提供一个高效的TCP/IP协议栈,以便这些设备可以方便地访问Internet或局域网。它支持IPv4和IPv6协议,并实现了TCP、UDP、IP、ICMP、ARP、DNS等协议,可以满足各种嵌入式设备的网络通信需求。
LWIP的源代码开放,可以在开源协议下自由使用和修改。它已经被广泛应用于各种嵌入式系统,如ARM、AVR、MSP430等,以及各种嵌入式操作系统,如FreeRTOS、uC/OS、VxWorks等。
基础知识
OSI七层模型
TCP/IP五层模型
LwIP的模型
常见协议
ARP协议
ARP(Address Resolution Protocol)协议是用于在网络层(如IPv4)和链路层(如以太网)之间进行地址解析的协议。它的主要功能是将一个IP地址解析为对应的物理地址(如MAC地址),以便能够在网络上发送数据包。
当一个主机需要向另一个主机发送数据包时,它需要知道目标主机的物理地址,而这个物理地址可以通过发送ARP请求来获取。ARP请求包含源主机的IP地址和MAC地址,以及目标主机的IP地址,当目标主机收到ARP请求后,会将自己的MAC地址作为响应发送给源主机,从而实现了地址解析。
ICMP协议
ICMP(Internet Control Message Protocol)协议是一种在互联网协议(IP)网络中使用的控制协议,用于在网络中传递错误和状态信息。它的主要作用是帮助网络管理员和网络应用程序发现和诊断网络中的问题,以便进行相应的处理。
ICMP协议常用于网络中的诊断和测量,它可以用于测试网络是否能够正常连接、测试网络的响应时间和带宽等。ICMP协议的消息被称为ICMP报文,它们被封装在IP数据报中进行传输。
ICMP协议可以发送多种类型的消息,其中一些常见的消息类型包括:
- 回显请求和回显应答:用于测试网络是否能够正常连接;
- 目的地不可达消息:用于指示数据包无法到达目标主机;
- 时间超过消息:用于指示数据包在传输过程中超时;
- 重定向消息:用于指示主机将数据包发送到另一个网关。
总的来说,ICMP协议在互联网协议(IP)网络中扮演着重要的角色,它能够帮助网络管理员和网络应用程序发现和诊断网络中的问题,并提供一些基本的网络测试和诊断工具。
DHCP协议
DHCP(Dynamic Host Configuration Protocol)是一种用于动态分配IP地址和其他网络配置信息的协议。DHCP允许网络管理员从一个中心位置管理和分配IP地址,以及其他网络配置信息,如子网掩码、默认网关和DNS服务器等。
DHCP协议的工作方式如下:
- 客户端主机发送一个DHCP请求广播,以请求IP地址和其他配置信息;
- DHCP服务器接收到请求后,为客户端主机分配一个可用的IP地址,并将其他网络配置信息一并发送给客户端主机;
- 客户端主机接收到DHCP响应后,使用分配的IP地址和其他配置信息连接到网络。
DHCP协议可以减轻网络管理员的工作负担,因为它可以自动管理和分配IP地址,而无需手动分配每个主机的IP地址和其他配置信息。此外,DHCP还支持地址重用和地址租用,可以将已经不再使用的IP地址分配给其他主机使用,从而提高IP地址的利用率。
总的来说,DHCP协议是一个简单而有效的协议,它为网络管理员提供了一种简单的方法来管理和分配IP地址和其他网络配置信息。它能够减轻网络管理员的工作负担,同时提高网络的可管理性和可扩展性。
DNS协议
DNS(Domain Name System)是一种用于将域名解析为IP地址的分布式数据库系统。它充当了互联网中的“电话簿”,将易于记忆的域名转换为计算机更易处理的IP地址。
DNS的工作原理如下:
- 客户端主机向本地DNS服务器发出域名解析请求;
- 如果本地DNS服务器具有所需的解析信息,则它会将该信息返回给客户端主机;
- 如果本地DNS服务器没有所需的解析信息,则它将向其他DNS服务器发送查询请求,直到找到所需的解析信息为止;
- 找到所需的解析信息后,本地DNS服务器会将该信息缓存起来,以便在将来的查询中更快地响应。
DNS具有以下几个重要的特点:
- 分布式:DNS数据库分布在多个服务器上,没有单个服务器拥有完整的数据库。
- 层次结构:DNS数据库被组织成一个层次结构,顶级域名服务器位于最上层,而每个域名的子域名服务器位于下一层。
- 快速:DNS可以使用本地缓存和分布式数据库来加快解析速度。
- 动态:DNS数据库可以随时更改,以反映新的IP地址和域名映射关系。
总的来说,DNS是互联网中非常重要的一个组成部分,它能够将易于记忆的域名转换为计算机更易处理的IP地址,为互联网用户提供了更方便的访问方式。
LwIP API
LwIP协议包含以下6部分API
- Socket API:提供了类似于BSD socket API的接口,包括socket()、bind()、listen()、accept()、connect()、recv()和send()等函数,使得开发人员可以使用熟悉的套接字编程模型来实现网络通信。
- Netconn API:提供了一组基于连接的API,包括netconn_new()、netconn_bind()、netconn_listen()、netconn_accept()、netconn_connect()、netconn_recv()和netconn_send()等函数,使得开发人员可以通过连接来实现网络通信。
- Raw API:提供了一组原始的API,包括raw_new()、raw_bind()、raw_sendto()和raw_recv()等函数,使得开发人员可以直接访问网络数据包,实现更高级别的网络协议。
- SNMP API:提供了一组简单网络管理协议(SNMP)API,包括snmp_init()、snmp_get_value()和snmp_set_value()等函数,使得开发人员可以实现远程设备管理和监控。
- DNS API:提供了一组域名解析系统(DNS)API,包括dns_gethostbyname()函数,使得开发人员可以实现通过域名解析获取IP地址的功能。
- PPP API:提供了一组点对点协议(PPP)API,包括ppp_connect()和ppp_close()等函数,使得开发人员可以实现在串口上使用PPP协议进行网络通信。
使用方法待补充
tcp_new
tcp_bind
tcp_listen
tcp_accept
tcp_connect
tcp_write
tcp_sent
tcp_recv
tcp_recved
轮询
tcp_poll
tcp_close
tcp_err
tcp_abort
Socket
LwIP除了提供Raw API,还提供了Socket编程接口,因为Socket最初在UNIX上使用,所以使用LwIP进行Socket编程通常需要在操作系统的支持下进行,可以使用常见的FreeRTOS以便实现更高效、更稳定的网络通信。
Socket是一种计算机网络通信中的编程接口(API),它提供了一种标准的方法,使得应用程序可以通过网络与其他应用程序进行通信。Socket通常用于在网络中实现客户端和服务器之间的通信,而且是基于TCP/IP协议族的通信。
使用Socket的好处是Socket可以将网络模型中底层的协议以及硬件接口进行抽象,统一操作接口,方便跨平台移植。
LwIP的Socket接口与Linux的功能大体一致,详见Linux网络IO基础
大端模式与小端模式
高位存在低地址处,低位存在高地址处是大端模式
+------+------+------+------+------+------+------+------+
addr | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+------+------+------+------+------+------+------+------+
byte | 12 | 34 | | | | | | |
+------+------+------+------+------+------+------+------+
高位存在高地址处,低位存在低地址处是小端模式
+------+------+------+------+------+------+------+------+
addr | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+------+------+------+------+------+------+------+------+
byte | 34 | 12 | | | | | | |
+------+------+------+------+------+------+------+------+
网络协议通常采用大端模式,因为不同的计算机使用的字节序可能不同,通过规定使用大端模式可以保证数据的互相传输的正确性,因此需要使用字节序转换的API
地址字节序
相关API
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
h表示host主机,to就是to,n是net网络,l是long,s是short
htonl的意思是host to network long主机字节序转换为网络字节序(32位)
常用于将端口号或者主机号转换为二进制以便计算机识别
IP地址转换
//将IP地址(IPv4或IPv6)从文本格式转换为网络格式的函数
#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);
//将网络格式的IP地址(IPv4或IPv6)转换为文本格式
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
参数:
- 参数af表示要转换的地址族,可以是AF_INET或AF_INET6,分别表示IPv4和IPv6;
- 参数src是包含要转换的IP地址的字符串;
- 参数dst是指向存放转换后的地址的缓冲区的指针。
返回值:
- 返回0表示转换失败
- 返回1表示转换成功
- 如果src参数无效,则返回-1。
//将一个点分十进制形式的IPv4地址转换为32位无符号整数表示的网络字节序
#include <arpa/inet.h>
in_addr_t inet_addr(const char *cp);
cp
参数是指向点分十进制形式IPv4地址字符串的指针。- 函数返回值是转换后的32位无符号整数,如果转换失败则返回
INADDR_NONE
。
注意,
inet_addr
返回的是网络字节序的32位无符号整数表示,需要使用网络字节序转主机字节序的函数(例如ntohl
)进行转换后才能得到可读性较强的IP地址表示。
inet_addr
和inet_pton
都是用来将IP地址转换为网络字节序的整数表示的函数,不同之处在于:
inet_addr
函数将一个点分十进制字符串形式的IP地址转换为一个32位的整数。这个函数在处理不合法的IP地址时会返回INADDR_NONE
宏定义的无效IP地址值。inet_pton
函数则是将一个点分十进制字符串形式的IP地址转换为一个二进制的网络字节序的IP地址,并存储在一个指定的内存中。同时,它支持IPv4和IPv6两种地址格式的转换。
因为inet_addr
存在一些缺陷和安全问题,所以在实际使用中推荐使用inet_pton
来完成IP地址的转换。此外,对于IPv6地址的转换,只有inet_pton
可以支持。
后续待补充