当前位置: 首页 > 科技观察

使用鸿蒙Hi3861完成WiFi热点连接并启动TCPSocketServ

时间:2023-03-20 16:31:41 科技观察

更多信息请访问:与华为官方共建的鸿蒙技术社区https://harmonyos.51cto.com/#zz本次使用Hi3861完成连接到Wifi热点,启动TCPSocketServer,接收消息反馈给TcpCLient。1.连接到Wi-Fi热点。主要方法是启动开发板Wifi,然后设置热点和密码等配置信息,然后连接热点。1、首先定义两个Wifi监听器,一个用于连接变化,一个用于状态变化,并注册监听器。重要的是OnWifiConnectionChanged连接状态事件处理程序。该函数在连接成功后会设置全局变量g_connected=1,表示已经连接成功。WifiEventeventListener={.OnWifiConnectionChanged=OnWifiConnectionChanged,.OnWifiScanStateChanged=OnWifiScanStateChanged};WifiErrorCodeerrCode=RegisterWifiEvent(&eventListener);voidOnWifiConnectionChanged(intstate,WifiLinkedInfo*info){if(!info)返回;if(state==WIFI_STATE_AVALIABLE){g否则{g_connected=0;}}2。启动WifiEnableWifi();3.设置Wifi热点信息并返回NetworkIdWifiDeviceConfigapConfig={};strcpy(apConfig.ssid,"MyWifi");strcpy(apConfig.preSharedKey,"12345678");apConfig.securityType=WIFI_SEC_TYPE_PSK;intnetId=-1;AddDeviceConfig(&apConfig,&netId);4、连接热点,此时注意g_connected变量,true表示已连接,false表示未连接。此状态在事件处理函数中设置。当连接不成功时,系统会循环等待,直到事件设置值。ConnectTo(netId);while(!g_connected){osDelay(10);}2、连接网络,找到wlan0的网络接口,然后启动DHCP客户端获取IP地址。structnetif*iface=netifapi_netif_find("wlan0");if(iface){err_tret=netifapi_dhcp_start(iface);osDelay(300);}3.启动TcpSocketServer并收发消息1.创建SocketServer,设置服务端口,启动listeningintsockfd=socket(AF_INET,SOCK_STREAM,0);structsockaddr_inserverAddr={0};serverAddr.sin_family=AF_INET;serverAddr.sin_port=htons(port);serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);绑定(sockfd,(structsockaddr*)&serverAddr,sizeof(serverAddr));intbacklog=1;listen(sockfd,backlog)2.客户端连接。接收客户端消息并发回。请注意,连接后,将创建一个新的套接字文件描述。intconnfd=-1;connfd=accept(sockfd,(structsockaddr*)&clientAddr,&clientAddrLen);recv(connfd,request,sizeof(request),0);send(connfd,request,strlen(request),0);3.关闭TcpSocketServerlwip_close(connfd);lwip_close(socketfd);4、联网后,关闭DHCP客户端,断开Wifi,清除热点配置信息,禁用Wifi。err_tret=netifapi_dhcp_stop(iface);Disconnect();RemoveDevice(netId);DisableWifi();5.测试情况如下:1、启动开发板,连接Wifi热点,启动TcpServer2、TcpClient(网络调试助手)连接开发板(HiBurn)的TcpServer。3、TcpClient输入数据并发送,TcpServer接收数据并返回给TcpClient。6.所有源码我都做了注释,希望大家参考。#include#include#include#include#include#include"ohos_init.h"#include"cmsis_os2.h"#include"wifi_device.h"#include"lwip/netifapi.h"#include"lwip/api_shell.h"#include"lwip/sockets.h"//接收和发送的数据staticcharrequest[128]="";//未连接hotspot=0,connectedhotspot=1staticintg_connected=0;//输出连接信息字符串//示例打印内容-->bssid:38:47:BC:49:01:FA,rssi:0,connState:0,reason:0,ssid:MyMobilelevoidPrintLinkedInfo(WifiLinkedInfo*info){if(!info)return;staticcharmacAddress[32]={0};unsignedchar*mac=info->bssid;snprintf(macAddress,sizeof(macAddress),"%02X:%02X:%02X:%02X:%02X:%02X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);printf("bssid:%s,rssi:%d,connState:%d,reason:%d,ssid:%srn",macAddress,info->rssi,info->connState,info->disconnectedReason,info->ssid);}//连接状态改变事件处理voidOnWifiConnectionChanged(intstate,WifiLinkedInfo*info){if(!info)return;//输出类似内容:OnWifiConnectionChanged31,state=1,info=printf("%s%d,state=%d,info=rn",__FUNCTION__,__LINE__,state);PrintLinkedInfo(info);//根据连接状态设置g_connectedif(state==WIFI_STATE_AVALIABLE){g_connected=1;}else{g_connected=0;}}//扫描状态改变事件处理voidOnWifiScanStateChanged(intstate,intsize){printf("%s%d,state=%X,size=%drn",__FUNCTION__,__LINE__,state,size);}voidDisconnectTcpSocket(intconnfd){sleep(1);printf("do_disconnect...rn");lwip_close(connfd);sleep(1);//fordebug}voidCloseTcpSocket(intsocketfd){printf("do_cleanup...rn");lwip_close(socketfd);}staticvoidTcpServerHandler(void){ssize_tretval=0;unsignedshortport=9118;//创建通信Socket,并返回一个套接字文件描述符第一个参数IpV4,第二个参数SOCK_STREAM类型,第三个指的是使用的协议intsockfd=socket(AF_INET,SOCK_STREAM,0);//客户端地址和地址长度structsockaddr_inclientAddr={0};socklen_tclientAddrLen=sizeof(clientAddr);//serveraddressstructsockaddr_inserverAddr={0};serverAddr.sin_family=AF_INET;//htons将整型变量从主机字节序转换为网络字节序,即整型在地址空间的存储方式变为高字节存储在内存低位地址serverAddr.sin_port=htons(port);//监听本机所有IP地址,INADDR_ANY=0x0//将主机数转换为无符号长整型serverAddr的网络字节序。sin_addr.s_addr=htonl(INADDR_ANY);//服务器绑定端口retval=bind(sockfd,(structsockaddr*)&serverAddr,sizeof(serverAddr));if(retval<0){printf("bindfailed,%ld!rn",retval);CloseTcpSocket(sockfd);return;}printf("bindtoport%dsuccess!rn",port);//开始监听,backlog是指Pending连接队列的最大长度。当队列已满,并且有新的连接请求到达时,客户端出现ECONNREFUSED错误。如果支持重传,则忽略该请求。intbacklog=1;retval=listen(sockfd,backlog);if(retval<0){printf("listenfailed!rn");CloseTcpSocket(sockfd);return;}printf("listenwith%dbacklogsuccess!rn",backlog);intoouterFlag=1;while(outerFlag){//接受客户端连接,成功则返回一个代表连接的socket。clientAddr参数会携带客户端主机和端口信息;failurereturns-1//从Pending连接队列中获取第一个连接,根据sockfd的socket协议和地址族创建新的socket文件描述,并返回。//后续的接收和发送都在代表连接的socket上进行;之后,sockfd仍然可以继续接受其他客户端的连接,//UNIX系统上经典的并发模型是“oneprocessperconnection”——创建子进程处理Connection,父进程继续接受其他客户端的连接并发型号intconnfd=-1;connfd=accept(sockfd,(structsockaddr*)&clientAddr,&clientAddrLen);if(connfd<0){printf("acceptfailed,%d,%drn",connfd,errno);CloseTcpSocket(sockfd);outerFlag=0;}printf("acceptsuccess,connfd=%d!rn",connfd);//inet_ntoa:将网络地址转换为以“.”分隔的字符串格式。ntohs:从网络字节序转换为主机字节序的16位数字。printf("clientaddrinfo:host=%s,port=%drn",inet_ntoa(clientAddr.sin_addr),ntohs(clientAddr.sin_port));innerFlag=1;//接收消息并发回while(innerFlag){//后续的接收和发送都在代表连接的socket上进行;//接收新的Socket文件描述信息。retval=recv(connfd,request,sizeof(request),0);if(retval<0){printf("recvrequestfailed,%ld!rn",retval);innerFlag=0;}elseif(retval==0){//对方主动断开连接printf("clientdisconnected!rn");innerFlag=0;}else{printf("recvrequest{%s}fromclientdone!rn",request);//发送数据retval=send(connfd,request,strlen(request),0);if(retval<=0){printf("sendresponsefailed,%ld!rn",retval);innerFlag=0;}printf("sendresponse{%s}toclientdone!rn",request);//清空缓冲区memset(&request,0,sizeof(request));}DisconnectTcpSocket(connfd);outerFlag=0;}CloseTcpSocket(sockfd);}staticvoidTcpServerTask(void*arg){(void)arg;//首先定义两个Wifi监听器,一个用于连接变化,一个用于状态变化WifiEventeventListener={.OnWifiConnectionChanged=OnWifiConnectionChanged,.OnWifiScanStateChanged=开启无线网络canStateChanged};//等待10个系统Tick,每个tick多少us,计算方法=1000*1000/osKernelGetTickFreq()osDelay(10);//注册WifiErrorCoderCode=RegisterWifiEvent(&eventListener);printf("RegisterWifiEvent:%drn",errCode);//设置Wifi热点信息WifiDeviceConfigapConfig={};strcpy(apConfig.ssid,"MyMobile");strcpy(apConfig.preSharedKey,"12345678");apConfig.securityType=WIFI_SEC_TYPE_PSK;intnetId=-1;//EnableWifierrCode=EnableWifi();printf("EnableWifi:%drn",errCode);osDelay(10);//设置Wifi热点配置信息,返回生成的网络Id-netId。errCode=AddDeviceConfig(&apConfig,&netId);printf("AddDeviceConfig:%drn",errCode);//根据网络Id连接Wifi热点g_connected=0;errCode=ConnectTo(netId);printf("ConnectTo(%d):%drn",netId,errCode);//如果连接没有完成,会一直等待。g_connected状态将在事件中设置。while(!g_connected){osDelay(10);}printf("g_connected:%drn",g_connected);osDelay(50);//开始联网业务,找到netifname=wlan0的netif。structnetif*iface=netifapi_netif_find("wlan0");if(iface){//启动DHCP客户端获取IP地址err_tret=netifapi_dhcp_start(iface);printf("netifapi_dhcp_start:%drn",ret);//等待DHCP服务器反馈地址osDelay(300);//执行线程安全的网络方法,第二个参数为voidFunc,第三个参数为errFunc。如果没有errFunc,则执行voidFunc。//netifapi_dhcp_start/netifapi_dhcp_stop等都是调用的netifapi_netif_common方法。//dhcp_clients_info_show显示信息/*server:server_id:192.168.43.1mask:255.255.255.0,1gw:192.168.43.1T0:3600T1:1800T2:3150clients<1>:mac_idxmacaddrstateleasetriesrto0b4c9b9af69f8192.168.43.5610012*/ret=netifapi_netif_common(iface,dhcp_clients_info_show,NULL);printf("netifapi_netif_common:%drn",ret);}TcpServerHandler();//网络服务结束,断开连接DHCPerr_tret=netifapi_dhcp_stop(iface);printf("netifapi_dhcp_stop:%drn",ret);//断开Wifi热点连接Disconnect();//移除Wifi热点配置RemoveDevice(netId);//关闭WifierrCode=DisableWifi();printf("DisableWifi:%drn",errCode);osDelay(200);}staticvoidTcpServerEntry(void){osThreadAttr_tattr;attr.name="TcpServerTask";attr.attr_bits=0U;attr.cb_mem=NULL;attr.cb_size=0U;attr.stack_mem=NULL;attr.stack_size=10240;attr.priority=osPriorityNormal;if(osThreadNew((osThreadFunc_t)TcpServerTask,NULL,&attr)==NULL){printf("SunLaoTest-FailCreate");}}APP_FEATURE_INIT(TcpServerEntry);更多信息请访问:与华为合作共建鸿蒙技术社区https://harmonyos.51cto.com/#zz