#打卡不停更#【FFH】OpenHarmony设备开发(七)- LWIP 原创
@[TOC]
前言
LWIP全称为LIght Weight IP,本意便是轻量化的小型TCP协议,旨在保留TCP的功能下尽量减少对系统资源的占用,LWIP多用于轻量化的设备上.当然LWIP功能不只是支持TCP协议传输,还支持了DHCP协议动态分配IP地址,IP协议等等.
OpenHarmony轻量化系统连接WIFI便多数都为LWIP协议,本文便主要介绍轻量化系统连接WIFI的分配IP步骤
对于小熊派nano而言,lwip的主要头文件都保存在了该地址下:
//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/lwip
netif网络接口
首先我们要认识到netif结构体,该结构体是LWIP从硬件中抽象出来的网卡(网络接口),并且该结构体还是个链表结构,即支持多个网卡配置.我们使用LWIP进行配置IP时,netif结构体必不可少.
netif结构体的定义存放在:vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/lwip/netif.h
介绍一些主要的变量:
struct netif *next;
该变量便表示了netif是链表结构,提供了配置多个网卡的接口,当需要配置第二个网络接口时,便指向该指针便可配置第二网络接口,第三第四如上原理.
本文主要介绍ipv4的相关变量(因为ipv4用的比较多)
这三个数据分别存放了主机的IP,子网掩码,网关.(但经过查看此数据,好像小熊派nano的IP地址和子网掩码反了(有可能存放相关地址的时候传递的变量反了?))
进一步查看IP,子网掩码,网关的ip_addr_t结构体,我们便能从里面看到了存放了ip4和ip6的地址,其中ip4变量是以无符号整数类型保存,ip4_addr_t结构体里面只有一个unsigned int的addr变量.
我们想获取IP,子网掩码,网关的数据方法如下:
static struct netif *g_lwip_netif = NULL; //创建该结构体
g_lwip_netif->ip_addr.u_addr.ip4.addr
g_lwip_netif->netmask.u_addr.ip4.addr
g_lwip_netif->gw.u_addr.ip4.addr
**char hostname[NETIF_HOSTNAME_MAX_LEN];**netif主机名称
**u8_t hwaddr[NETIF_MAX_HWADDR_LEN];**该设备MAC地址
DHCP动态分配IP
DHCP全称为Dynamic Host Configuration Protocol,动态主机配置协议.顾名思义,其作用便是可以动态分配IP地址,提高IP地址的使用效率.
主要介绍小熊派nano的实现:
- 创建netif结构体,并对此初始化
- 启动dhcp
static struct netif *g_lwip_netif = NULL; //创建该结构体
g_lwip_netif = netifapi_netif_find("wlan1");
if (g_lwip_netif) //判断dhcp是否初始化成功
{
dhcp_start(g_lwip_netif); //启动DHCP
printf("begain to dhcp");
}
一些相关的API接口:
-
err_t dhcp_is_bound(struct netif *netif);
获取网络接口的DHCP协商状态,可以使用该api循环判断dhcp是否正常使用,判断成功再进行下一步工作.
返回值为0即是成功
-
err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,netifapi_errt_fn errtfunc);
以线程安全的方式调用与netif相关的API
参数 | 说明 |
---|---|
netif | netif网络接口 |
voidfunc | 回调函数,当errtfunc为NULL时调用 |
errtfunc | 回调函数 |
void dhcp_clients_info_show(struct netif *netif_p);
样例:netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);
打印主机以及设备的IP等相关信息
-
err_t netifapi_netif_get_addr(struct netif *netif, ip4_addr_t *ipaddr, ip4_addr_t *netmask, ip4_addr_t *gw);
获取netif内保存的设备的IP,子网掩码,网关信息,将ip保存到ipaddr,子网掩码保存到netmask,网关保存到gw.
-
struct netif *netifapi_netif_find(const char *name);
寻找一个名为name的网络接口,并将此网络接口作为返回值返回
-
err_t netifapi_dhcps_start(struct netif *netif, char *start_ip, u16_t ip_num);
启动DHCP服务端,提供客户端连接,常用于设备作为热点时所选择的DHCP启动方式
参数一:网络接口
参数二:起始IP地址
参数三:IP地址数量
其中如果DHCPv4使用默认配置,参数二和三都需要为NULL
netifapi_dhcps_start(g_lwip_netif, 0, 0);
- 更多的api接口可以参考netifapi.h和dhcp.h
存放地址:device/soc/hisilicon/hi3861v100/sdk_liteos/third_party/lwip_sack/include/lwip
静态分配IP
关键API接口为:err_t netifapi_netif_set_addr(struct netif *netif,const ip4_addr_t *ipaddr,const ip4_addr_t *netmask,const ip4_addr_t *gw);
前文中有了一个获取IP信息,这便有一个设置IP地址,我们可以通过这一个API便完成了对IP地址的分配,十分的便捷!!
- 创建netif结构体,并对此初始化
- 设置IP,子网掩码,网关
- 调用API完成分配IP
static struct netif *g_lwip_netif = NULL; //创建该结构体
g_lwip_netif = netifapi_netif_find("wlan1");
ip4_addr_t bp_gw;
ip4_addr_t bp_ipaddr;
ip4_addr_t bp_netmask;
IP4_ADDR(&bp_ipaddr, 192, 168, 1, 110);
IP4_ADDR(&bp_gw, 192, 168, 1, 1);
IP4_ADDR(&bp_netmask, 255, 255, 255, 0);
netifapi_netif_set_addr(g_lwip_netif, &bp_ipaddr, &bp_netmask, &bp_gw);
ip地址打印
- 直接打印IPv4地址
ip4_addr_t Ipv4_Addr;
unsigned char *read = (unsigned char *)&Ipv4_Addr.addr;
for (int i = 0; i < 4; i++)
{
printf("%d", *(read + i));
if (i != 3)
printf(".");
else
printf("\n");
}
- IPv4十进制转字符串
ip4_addr_t Ipv4_Addr;
const unsigned int num=Ipv4_Addr.addr;
char strTemp[20]; //存放IPV4地址
sprintf(strTemp, "%d.%d.%d.%d",
(num & 0x000000ff),
(num & 0x0000ff00) >> 8,
(num & 0x00ff0000) >> 16,
(num & 0xff000000) >> 24);