OpenHarmony轻量设备获取网络中设备IP方式-组播

这篇具有很好参考价值的文章主要介绍了OpenHarmony轻量设备获取网络中设备IP方式-组播。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、简介

​ 在Openharmony的轻量和小型系统中,受限于cpu与内存资源等原因,网络协议一般使用lwip的实现。而且受限资源影响,lwip的socket数与端口数都通过宏定义控制在7-8个以内。在物联IOT实际应用中,经常会出现多台IOT设备在未知对方IP的状态下,需要对多台IOT设备进行控制与通信。此时可以通过组播的方式获取对方设备的IP地址,后续就可以对对方设备进行控制与通信。

另:

1.在IOT设备通信中,关于可信安全的问题,在Openharmony中可以使用hichain的可信安全进行认证。

2.在IOT设备通信中,Openharmony除了采用传统的组播与广播方式控制其它的IOT设备,还可以选择Openharmony的软总线来实现,而软总线的可信认证即是采用的hichain进行安全认证。

此两课题有时间再详述。

​ 本文通过代码示例,在两台不同的L0的轻量系统中通过组播获取对方设备的IP后,发送指定的信息。

二、组播

​ 组播指的是报文从一个源发出,被转发到一组特定的接收者,相同的报文在每条链路上最多有一份。相较于传统的单播和广播,组播可以有效地节约网络带宽、降低网络负载。

​ 组播是一种允许一个或多个组播源发送同一报文到多个接收者的技术。组播源将一份报文发送到特定的组播地址,组播地址不同于单播地址,它不属于特定某个主机,而是属于一组主机。一个组播地址表示一个群组,需要接收组播报文的接收者都加入这个群组。

​ 广播传输数据源必须与用户在同一网段,组播可以跨网段传输。

​ 为了使组播源和组播组成员进行通信,需要提供网络层组播使用的IP组播地址。

2.1 组播地址

​ D类地址空间分配给IPv4组播使用,地址范围从224.0.0.0到239.255.255.255.

​ 224.0.0.0~224.0.0.255 永久组地址,为路由协议预留的IP地址,用于标识一组特定的网络设备,供路由协议 、拓扑查找等使用,不用于组播转发。

​ 224.0.1.0~239.255.255.255 均可作为组播地址使用,只是组范围有所不同,具体范围使用可以查找IPv4组播地址规范。

三、Openharmony的两类L0设备

3.1 拓维Niobe开发板

  • 代码分支

    https://gitee.com/talkweb_oh/niobe

  • wifi连接示例代码

​ https://gitee.com/talkweb_oh/niobe/tree/master/applications/app/TW301_Network_wifista

  • udp示例

    https://gitee.com/talkweb_oh/niobe/tree/master/applications/app/TW305_Network_udpclient

    https://gitee.com/talkweb_oh/niobe/tree/master/applications/app/TW305_Network_udpserver

  • tcp示例

    https://gitee.com/talkweb_oh/niobe/tree/master/applications/app/TW304_Network_tcpclient

    https://gitee.com/talkweb_oh/niobe/tree/master/applications/app/TW304_Network_tcpserver

3.2 小熊派BearPi-HM Nano开发板

  • 代码分支

​ https://gitee.com/bearpi/bearpi-hm_nano

  • wifi连接示例

    https://gitee.com/bearpi/bearpi-hm_nano/tree/master/applications/BearPi/BearPi-HM_Nano/sample/D2_iot_wifi_sta_connect

  • udp示例

    https://gitee.com/bearpi/bearpi-hm_nano/tree/master/applications/BearPi/BearPi-HM_Nano/sample/D3_iot_udp_client

  • tdp示例

    https://gitee.com/bearpi/bearpi-hm_nano/tree/master/applications/BearPi/BearPi-HM_Nano/sample/D4_iot_tcp_server

四、组播获取代码示例

4.1 常量定义

constexpr const char* MULTICAST_DATA = "multicast"; // 组播测试数据
constexpr const char* MULTICAST_IP = "234.3.3.3";   // 组播地址
constexpr uint32_t MULTICAST_PORT = 9000;		    // 组播端口
constexpr uint32_t SEND_DATA_PORT = 9001;		    // 发送数据端口

4.2 组播源

void UdpSendThread(void)
{
    wifiConnect("wifi name", "wifi password");
    int udp_socket = CreateUdpSocket(); // 创建udp socket略过...
    if (udp_socket >= 0) {
        printf("CreateUdpSocket udp_socket:%d\n", udp_socket);
        // 指定发送的组播地址和端口
        struct sockaddr_in mcast_addr;
        memset(&mcast_addr, 0, sizeof(mcast_addr));
        mcast_addr.sin_family = AF_INET;
        mcast_addr.sin_addr.s_addr = inet_addr(MULTICAST_IP);
        mcast_addr.sin_port = htons(MULTICAST_PORT);
    }
    while (true) {
        // 发送测试数据multicast
        int sendLength = sendto(udp_socket, MULTICAST_DATA, 9, 0, (struct socketaddr*)&mcast_addr, sizeof(mcast_addr));
        if (sendLength < 0) {
            printf("sendto udp_socket:%d fail,sendLength:%d", udp_socket, sendLength);
        } else {
            g_SendUdpSucc++;	
            if (g_SendUdpSucc >= 10) {
                break;	// 此为测试,组播报文只发送10次,实际项目中应在从接收者收到应答数据包时,停止发送。
            }
        }
        Delay(1000);
    }
    close(udp_socket);
}

4.3 组播接收端

void UdpRecvThread(void)
{
	wifiConnect("wifi name", "wifi password");
    struct sockaddr_in server_socket;
    int upd_socket = CreateUdpSocket();
    if (udp_socket >= 0) {
        bzero(&server_sock, sizeof(server_sock));
        server_sock.sin_family = AF_INET;
        server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
        server_sock.sin_port = htons(MULTICAST_PORT);
        
        // 调用bind绑定socket地址
        if (bind(udp_socket, (struct sockaddr*)&server_socket, sizeof(struct sockaddr)) == -1) {
            perror("bind error\r\n");
            closesocket(udp_socket);
            exit(1);
        }
        struct ip_mreq mreq;
        // 加入组播,接收组播信息
        mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_IP);
        mreq.imr_interface.s_addr = htonl(INADDR_ANY);
        int error = setsocket(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
        if (error < 0) {
            printf("setsocket fail error:%d\r\n", error);
            closesocket(udp_socket);
            exit(1);
        }
        while (true) {
            printf("select wait....\r\n");
            struct sockaddr_in recvAddr;
            memset(recvBuff, 0, sizeof(recvBuff));
            memset(&recvAddr, 0, sizeof(struct sockaddr));
            int sinSize = sizeof(struct sockaddr_in);
            int ret = recvfrom(udp_socket, recvBuff, sizeof(recvBuff)) - 1, 0, (struct sockaddr*)&recvAddr, (socklen_t *)&sinSize);
            printf("recv from UDP client IP:%s\r\n", inet_ntoa(recvAddr.sin_addr));
            printf("recv data:%s\r\n", recvBuff); // 组播测试数据"multicast"
            osDelay(10);
            // 校验组播数据
            if (strlen(recvBuff) == 9 && memcmp(recvBuff, MULTICAST_DATA, 10) == 0) {
                memset(remoteIp, 0, IPADDR_LEN);
                strcpy(remoteIp, inet_ntoa(recvAddr.sin_addr));
                printf("get peer device IP:%s\r\n", remoteIp);
                break;
            }
		}
        closesocket(udp_socket);
    }
}

4.4 通过获取的远端地址remoteIp,发送数据到对端设备

void TcpSendThread()
{
    struct sockaddr_in sendAddr;
    socklen_t addrLen = sizeof(sendAddr);
    // tcp socket
    int sock_fd = -1;
    if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        exit(1);
    }
    
    sendAddr.sin_family = AF_INET;
    sendAddr.sin_port = htons(SEND_DATA_PORT);
    sendAddr.sin_addr.s_addr = inet_addr(remoteIp);
    
    int ret = connect(sock_fd, (struct sockaddr*)&sendAddr, sizeof(sendAddr));
    if (ret != 0) {
        printf("connect server fail ret:%d\r\n", ret);
        closesocket(sock_fd);
        exit(1);
    }
    
    while (true) {
        bzero(recvBuff, sizeof(recvBuff));
        // 发送数据
        printf("send remote device %s:%d=>data:%s\r\n",remoteIp, SEND_DATA_PORT, sendData);
        sendto(sock_fd, sendData, strlen(sendData), 0, (struct sockaddr*)&sendAddr, addrLen);
        
        sleep(10);
        // 接收服务端返回应答数据
        memset(recvBuff, 0, sizeof(recvBuff));
        recvfrom(sock_fd, recvBuff, 0, (struct socketaddr*)&sendAddr, &addrLen);
        printf("recv remote device %s:%d=>data:%s\r\n", remoteIp, SEND_DATA_PORT, recvBuff);
    }
    closesocket(sock_fd);
}

4.5 组播端接受对端数据

void TcpRecvThread()
{
    struct sockaddr_in serverSock, clientSock, *cliAddr;
    int sinSize = sizeof(struct sockaddr_in);
    int sock_fd = -1;
    if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        exit(1);
    }
    bzero(&serverSock, sizeof(serverSock));
    serverSock.sin_family = AF_INET;
    serverSock.sin_addr.s_addr = htonl(INADDR_ANY);
    serverSock.sin_port = htons(SEND_DATA_PORT);
    
    if (bind(sock_fd, (struct sockaddr*)&serverSock, sizeof(struct sockaddr)) == -1) {
        printf("bind fail\r\n");
        closesocket(sock_fd);
        exit(1);
    }
    // listen监听
    if (listen(sock_fd, TCP_BACKLOG) == -1) {
        printf("listen fail\r\n");
        exit(1);
    }
    
    while (true) {
        if ((new_fd = accept(sock_fd, (struct sockaddr*)&clientSock,(socklen_t*)&sinSize)) == -1) {
            printf("accept fail\r\n");
        	closesocket(sock_fd);
            exit(1);
        }
        cliAddr = malloc(sizeof(struct sockaddr));
        if (cliAddr != NULL) {
            memcpy(cliAddr, &clientSock, sizeof(struct sockaddr));
        }
        ssize ret;
        while (true) {
            if ((ret = recv(new_fd, recvBuff, sizeof(recvBuff), 0)) == -1) {
                printf("recv fail\r\n");
            }
            printf("recv data:%s\r\n", recvBuff);
            sleep(2);
            
            if ((ret = send(new_fd, sendBuff, strlen(sendBuff) + 1, 0)) == -1) {
                printf("send fail\r\n");
            }
            printf("send data:%s\r\n", sendBuff);
            sleep(2);
        }
        printf("server exit\r\n");
        close(new_fd);
    }
    closesocket(sock_fd);
}

4.6 demo打印结果显示

拓维Niobe开发板:
OpenHarmony轻量设备获取网络中设备IP方式-组播,网络,tcp/ip,openharmony
小熊派BearPi-HM Nano开发板:
OpenHarmony轻量设备获取网络中设备IP方式-组播,网络,tcp/ip,openharmony文章来源地址https://www.toymoban.com/news/detail-645394.html

到了这里,关于OpenHarmony轻量设备获取网络中设备IP方式-组播的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenHarmony 设备开发 命令行方式 搭建开发环境

    OpenHarmony开发环境搭建有好几种方式,现在主要是DevEco Device Tool IDE开发环境。这种方式搭建环境过程简单,而且现在的IDE环境已经很完善了,稳定性也能接受。 HUAWEI DevEco Device Tool 安装使用官方文档地址: 文档中心 最早的命令行方式也有很多优势,比如在低配置的机器下用

    2024年01月24日
    浏览(33)
  • linux设置动态获取ip:如何在Linux中设置动态IP

    Linux设置动态获取IP的方法如下:使用命令进行设置: Linux设置动态获取IP的方法如下: 1. 使用ifconfig命令进行设置: 2. 使用dhclient命令进行设置: 3. 使用NetworkManager进行设置:

    2024年04月26日
    浏览(40)
  • Mysql中设置只允许指定ip能连接访问(可视化工具的方式)

    Mysql中怎样设置指定ip远程访问连接: Mysql中怎样设置指定ip远程访问连接_navicat for mysql 设置只有某个ip可以远程链接-CSDN博客 前面设置root账户指定ip能连接访问是通过命令行的方式,如果通过可视化工具比如Navicat来实现。 注: 博客: 霸道流氓气质-CSDN博客 1、使用Navicat连接

    2024年01月15日
    浏览(23)
  • 获取当前设备的IP

      在本地使用自带webUI的项目时,需要制定webUI的访问地址。 一般本地访问使用: 127.0.0.1 , 配置为可以从其他设备访问时,需要指定当前设备的IP,或者指定为 0.0.0.0 。   例如:使用locust的时候,因为某些特殊原因,我的电脑名称中有中文字符。当指定webUI访问地址指定

    2024年01月17日
    浏览(33)
  • 轻量级网络IP扫描器WatchYourLAN

    什么是 WatchYourLAN ? WatchYourLAN 是一款带有 Web GUI 的轻量级网络 IP 扫描器。支持使用不同的主题和色彩模式进行个性化设置。 扫描网络,首先要找到对应的网络接口,一般常见的包括 eth0 、 lo 、 docker0 等,可以在 SSH 客户端命令行,执行下面的命令 但是目前 WatchYourLAN 还不支

    2024年02月06日
    浏览(59)
  • 【wireshark】如何获取一个设备的IP地址

    开发中往往会出现无法知道设备正确的IP地址,从而无法连接到设备。 使用软件工具wireshark来获取设备IP地址。 可以实现不同网段捕获设备IP 1. 下载wireshark抓包程序 https://www.wireshark.org/download.html 以管理员的身份打开wireshark。(否则要点击一堆授权) 电脑用网线直连设备,然

    2024年01月21日
    浏览(30)
  • 使用java代码实现BacNet协议通过设备IP与设备ID同网段获取到对方设备数据

    本文章参考了很多博主的案列 收获很多很感谢他们 我把他们的文章标注出来 可能我的方法并不适合你 使用感兴趣伙伴们可以的效仿他们的一下 (13条消息) BacNet4j-跨网段-项目运用_森林猿的博客-CSDN博客 (13条消息) BACnet/IP之BACnet4j学习java代码例子属性读写01_夢_殤的博客-CSDN博

    2024年02月05日
    浏览(33)
  • vue2获取当前设备的 IP 地址以及位置信息

    data数据:

    2024年04月25日
    浏览(33)
  • 组播IP 映射 组播MAC

    1、在IP分类中,D类IP地址用于组播MAC。 2、在TCP/IP中,最常用的v4组播MAC地址的前24位固定为01005e,第25位固定为0,后23位由IP地址的后23位复制得出。 3、在D类组播IP中有5位未用,也就是说组播IP和组播MAC的映射并不唯一, 4、每一个组播MAC最多可映射对应32个组播IP。 5、备注:

    2024年02月02日
    浏览(25)
  • OpenHarmony轻量系统开发【5】驱动之GPIO点灯

    摘要 :本文简单介绍如何操作GPIO去点灯 适合群体 :适用于Hi3861开发板,L0轻量系统驱动开发 5.1点灯例程源码 先看最简单得LED灯闪烁操作 源码结构如下: 第一个BUILD.gn文件内容: 第二个BUILD.gn内容: led_demo.c内容: 编译后烧录进去,应该可以看到复位按键旁边的LED灯一直在

    2024年02月07日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包