往期知识点记录:
- 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总
- OpenHarmony之分布式软总线json_payload.c(一)
- OpenHarmony之分布式软总线json_payload.c(二)
- OpenHarmony之分布式软总线json_payload.c(三)
- OpenHarmony之分布式软总线json_payload.c(四)
- OpenHarmony之分布式软总线nstackx_common.c分析
- OpenHarmony之分布式软总线coap_discover.c(一)
- OpenHarmony之分布式软总线coap_discover.c(二)
- OpenHarmony之分布式软总线coap_discover.c(三)
- OpenHarmony之分布式软总线coap_discover.c(四)
- 持续更新中……
//接口状态
typedef enum {
STATUS_UP,
STATUS_DOWN
} InterfaceStatus;
//接口信息
typedef struct {
char ip[NSTACKX_MAX_IP_STRING_LEN];
InterfaceStatus status;
int flag;
} InterfaceInfo;
/*
函数功能: 获取网络接口信息
函数参数:
fd: 接口文件描述符
interfaceName: 接口名
length: 接口名长度
info: 用来保存获得到的接口信息
函数过程:
1. 检查各个参数
2. 声明 ifreq 结构体 ifreq结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的
3. 调用ioctl 获取 本地网络接口信息,接口是否处于活动状态且准备好传输数据 ,如果是 接口状态就是上传 那么info状态就是上传,否则接口就在下载
4. 调用ioctl 获取接口IP地址
5. 将ip地址以点分十进制复制到info中
*/
void GetInterfaceInfo(int fd, const char* interfaceName, int length, InterfaceInfo *info)
{
if (fd < 0 || info == NULL || interfaceName == NULL) {
return;
}
struct ifreq ifr; //ifreq 结构体 ifreq结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的
/*
struct ifreq {
char ifr_name[IFNAMSIZ]; //接口名
union
{ (IP地址,广播地址,子网掩码,MAC号,MTU等)
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ];
char ifru_newname[IFNAMSIZ];
__caddr_t ifru_data;
} ifr_ifru
}; */
memset_s(&ifr, sizeof(struct ifreq), 0, sizeof(struct ifreq));
//将接口名拷贝到ifreq
int ret = strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), interfaceName, length);
if (ret != EOK) {
SOFTBUS_PRINT("[DISCOVERY] CoapGetWifiIp ifr.ifr_name cpy fail\n");
return;
}
//ioctl 获取本地网络接口信息
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
return;
}
//接口是否处于活动状态且准备好传输数据 ,如果是 接口状态就是上传
if ((unsigned short int)ifr.ifr_flags & IFF_UP) {
info->status = STATUS_UP;
} else {
//否则接口就在下载
info->status = STATUS_DOWN;
info->ip[0] = '\0';
info->flag = 1;
return;
}
memset_s(&ifr, sizeof(struct ifreq), 0, sizeof(struct ifreq));
ret = strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), interfaceName, length);
if (ret != EOK) {
SOFTBUS_PRINT("[DISCOVERY] CoapGetWifiIp ifr.ifr_name cpy fail\n");
return;
}
//获取接口IP地址
if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
return;
}
//将ip地址以点分十进制复制到info中
ret = strcpy_s(info->ip, sizeof(info->ip),
inet_ntoa(((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr));
if (ret != EOK) {
SOFTBUS_PRINT("[DISCOVERY] CoapGetWifiIp cpy fail\n");
}
info->flag = 1;
return;
}
/*
函数功能: 获取wifi ip地址
函数参数:
ip: 用来保存获取到的ip
length: ip长度
详细:
1.创建一个socket套接字, 声明InterfaceInfo结构体,调用GetInterfaceInfo获取网络接口信息
*/
void CoapGetWifiIp(char *ip, int length)
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
return;
}
InterfaceInfo info = {0};
GetInterfaceInfo(fd, ETH, strlen(ETH) + 1, &info);
//获取以太网网络接口信息失败
if (!info.flag) {
memset_s(&info, sizeof(info), 0, sizeof(info));
GetInterfaceInfo(fd, WLAN, strlen(WLAN) + 1, &info);
}
if (!info.flag) {
close(fd);
return;
}
//将接口ip复制到ip中
if (strcpy_s(ip, length, info.ip) != EOK) {
SOFTBUS_PRINT("[DISCOVERY]copy ip to dst failed.\n");
}
close(fd);
}
/*
函数功能: 创建监听线程
函数返回值:成功返回1,否则返回非零
详细:
1.设置终端设备标志
2. 如果g_coapTaskId不为0,那么表示监听线程之前就创建好
3. 设置线程属性
4. 创建线程
*/
int CreateCoapListenThread(void)
{
g_terminalFlag = 1;
#if defined(__LITEOS_M__) || defined(__LITEOS_RISCV__)
if (g_coapTaskId != NULL) {
return NSTACKX_EOK;
}
osThreadAttr_t attr;
attr.name = "coap_listen_task";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
attr.priority = osPriorityNormal4; // COAP_DEFAULT_PRIO -> cmsis prio
g_coapTaskId = osThreadNew((osThreadFunc_t)CoapReadHandle, NULL, &attr);
if (g_coapTaskId == NULL) {
g_terminalFlag = 0;
SOFTBUS_PRINT("[DISCOVERY] create task fail\n");
return NSTACKX_EFAILED;
}
#else
if (g_coapTaskId != -1) {
return NSTACKX_EOK;
}
ThreadAttr attr = {"coap_listen_task", 0x800, 20, 0, 0};
int error = CreateThread((Runnable)CoapReadHandle, NULL, &attr, (unsigned int *)&g_coapTaskId);
if (error != 0) {
g_terminalFlag = 0;
SOFTBUS_PRINT("[DISCOVERY] create task fail\n");
return NSTACKX_EFAILED;
}
#endif
return NSTACKX_EOK;
}
/*
函数功能: 撤销监听线程
详细:
1.终端标识设置为0
2. 如果线程没有运行完毕,那么等待运行完成
*/
void ExitCoapListenThread(void)
{
g_terminalFlag = 0;
#if defined(__LITEOS_M__) || defined(__LITEOS_RISCV__)
if (g_coapTaskId != NULL) {
if (osThreadTerminate(g_coapTaskId) != 0) {
SOFTBUS_PRINT("[DISCOVERY] ExitCoapListenThread pthread_join fail\n");
return;
}
}
#else
if (g_coapTaskId != -1) {
int ret = pthread_join((pthread_t)g_coapTaskId, NULL);
if (ret != 0) {
SOFTBUS_PRINT("[DISCOVERY] ExitCoapListenThread pthread_join fail\n");
return;
}
}
#endif
}
/*
函数功能: 设备发现初始化
详细: 创建socket, 设置wifi事件, 创建处理消息队列线程,创建COAP监听线程
*/
int CoapInitDiscovery(void)
{
int ret = CoapInitSocket();
if (ret != NSTACKX_EOK) {
SOFTBUS_PRINT("[DISCOVERY] Init socket fail\n");
return ret;
}
ret = CoapInitWifiEvent();
if (ret != NSTACKX_EOK) {
SOFTBUS_PRINT("[DISCOVERY] Init wifi event fail\n");
return ret;
}
#if defined(__LITEOS_A__)
ret = CreateQueryIpThread();
if (ret != NSTACKX_EOK) {
SOFTBUS_PRINT("[DISCOVERY] Init query Ip fail\n");
return ret;
}
#endif
if (CreateMsgQueThread() != NSTACKX_EOK) {
return NSTACKX_EFAILED;
}
return CreateCoapListenThread();
}
/*
函数功能: 撤销设备发现
详细:
1.退出监听线程
2.撤销wifi事件
3.关闭socket
*/
int CoapDeinitDiscovery(void)
{
//
ExitCoapListenThread();
int rtn = CoapDeinitWifiEvent();
if (rtn != NSTACKX_EOK) {
return NSTACKX_EFAILED;
}
#if defined(__LITEOS_A__)
ExitQueryIpThread();
#endif
CoapDeinitSocket();
return NSTACKX_EOK;
}
/*
函数功能: 检查IP是否有效
详细:
1.判断ip是否为空,长度是否在范围内
2. 判断是否是0.0.0.0的ip
3. 判断是否是网关ip
*/
int CheckIpIsValid(const char *ip, int length)
{
if (ip == NULL || length < IP_MIN_LEN || length > IP_MAX_LEN) {
return -1;
}
if (strcmp(ip, "0.0.0.0") == 0) {
return -1;
}
int pos = length - 1;
if (ip[pos] == '1' && ip[pos - 1] == '.') {
return -1;
}
return 0;
}
/*
函数功能: 获取ip
详细:
1. 设置ip请求标志为1
2. 设置请求次数 (300/无限)
3. 调用CoapGetWifiIp获取wifi ip
4. 检查获取到的ip的有效性
*/
void CoapGetIp(char *ip, int length, int finite)
{
if (ip == NULL || length != NSTACKX_MAX_IP_STRING_LEN) {
return;
}
g_queryIpFlag = 1;
int count = finite ? GET_IP_TIMES : GET_IP_INFINITE;
while (g_queryIpFlag) {
CoapGetWifiIp(ip, length);
if (CheckIpIsValid(ip, strlen(ip)) == 0) {
break;
}
if (count == 0) {
break;
}
count--;
usleep(TEN_MS);
}
return;
}
写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请看下图提示: