This time, use Hi3861 to complete the connection of the Wifi hotspot, and start the TCP SocketServer, receive the message and send the message back to TcpCLient. |
1. Connect to Wifi hotspot
The main method is to start the development board Wifi, then set the configuration information such as hotspot and password, and then connect to the hotspot.
1. First define two Wifi listeners, one for connection change and one for state change, and register the listener.
The important one is the OnWifiConnectionChanged connection status event handler. This function will set the global variable g_connected=1 after the connection is successful, which means that the connection is successful.
WifiEvent eventListener = { .OnWifiConnectionChanged = OnWifiConnectionChanged, .OnWifiScanStateChanged = OnWifiScanStateChanged }; WifiErrorCode errCode = RegisterWifiEvent(&eventListener); void OnWifiConnectionChanged(int state, WifiLinkedInfo* info) { if (!info) return; if (state == WIFI_STATE_AVALIABLE) { g_connected = 1; } else { g_connected = 0; } }
2. Start Wifi
EnableWifi();
3. Set Wifi hotspot information and return NetworkId
WifiDeviceConfig apConfig = {}; strcpy(apConfig.ssid, "MyWifi"); strcpy(apConfig.preSharedKey, "12345678"); apConfig.securityType = WIFI_SEC_TYPE_PSK; int netId = -1; AddDeviceConfig(&apConfig, &netId);
4. Connect to the hotspot, pay attention to the g_connected variable at this time, true means connected, false means not connected.
This state is set in the event handler function. When the connection is not successful, the system will wait in a loop until the event sets the value.
ConnectTo(netId); while (!g_connected) { osDelay(10); }
2. Connect to the network, find the network interface of wlan0, and then start the DHCP client to obtain an IP address.
struct netif* iface = netifapi_netif_find("wlan0"); if (iface) { err_t ret = netifapi_dhcp_start(iface); osDelay(300); }
3. Start TcpSocketServer and send and receive messages
1. Create SocketServer, set the service port, and start monitoring
int sockfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serverAddr = {0}; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); int backlog = 1; listen(sockfd, backlog)
2. Client connection. Receive client messages and send them back. Note that after connection, a new Socket File Description will be created.
int connfd = -1; connfd = accept(sockfd, (struct sockaddr *)&clientAddr, &clientAddrLen); recv(connfd, request, sizeof(request), 0); send(connfd, request, strlen(request), 0);
3. Close TcpSocketServer
lwip_close(connfd); lwip_close(socketfd);
4. After networking, close the DHCP client, disconnect Wifi, remove the configuration information of the hotspot, and disable Wifi.
err_t ret = netifapi_dhcp_stop(iface); Disconnect(); RemoveDevice(netId); DisableWifi();
5. The test conditions are as follows:
1. Start the development board, connect to the Wifi hotspot, start TcpServer
2. TcpClient (network debugging assistant) connects to the TcpServer (HiBurn) of the development board.
3. TcpClient inputs data and sends it, and TcpServer receives it and sends it back to TcpClient.
Sixth, I have annotated all the source code, I hope you can refer to it.
#include <errno.h> #include <stdio.h> #include <string.h> #include <stddef.h> #include <unistd.h> #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" // Data received and sent static char request[128] = "" ; // Unconnected hotspot=0, connected hotspot=1 static int g_connected = 0; // Output connection information string // Print content sample --> bssid: 38:47:BC:49:01:FA, rssi: 0, connState: 0, reason: 0, ssid: MyMobile void PrintLinkedInfo(WifiLinkedInfo* info) { if (!info) return; static char macAddress [32] = {0}; unsigned char* 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); } // Connection state change event handling void OnWifiConnectionChanged(int state, WifiLinkedInfo* info) { if (!info) return; // Output similar content: OnWifiConnectionChanged 31, state = 1 , info = printf("%s %d, state = %d, info = rn", __FUNCTION__, __LINE__, state); PrintLinkedInfo(info); // Set g_connected according to the connection state if (state == WIFI_STATE_AVALIABLE) { g_connected = 1; } } else { g_connected = 0; } // Scanning state change event processing void OnWifiScanStateChanged(int state, int size) { printf("%s %d, state = %X, size = %drn", __FUNCTION__, __LINE__, state, size); } void DisconnectTcpSocket(int connfd) { sleep(1); printf("do_disconnect...rn"); lwip_close(connfd); sleep(1); // for debug } void CloseTcpSocket(int socketfd) { printf("do_cleanup ...rn"); lwip_close(socketfd); } static void TcpServerHandler(void) { ssize_t retval = 0; unsigned short port = 9118; // Create a communication socket and return a socket file descriptor. The first parameter IpV4, the second parameter SOCK_STREAM type, and the third refers to the protocol used int sockfd = socket(AF_INET, SOCK_STREAM, 0); // Client address and address length struct sockaddr_in clientAddr = {0}; socklen_t clientAddrLen = sizeof(clientAddr); // server address struct sockaddr_in serverAddr = {0}; serverAddr.sin_family = AF_INET; // h It is to change the integer variable from the host byte order to the network byte order, that is, the storage mode of the integer in the address space becomes the high byte and it is stored at the low address of the memory serverAddr.sin_port = htons(port); // monitor this machine INADDR_ANY=0x0 // Convert the host number into an unsigned long integer network byte order serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // server binding port retval = bind(sockfd, ( struct sockaddr *)&serverAddr, sizeof(serverAddr)); if (retval <0) { printf("bind failed, %ld!rn", retval); CloseTcpSocket(sockfd); return; } printf("bind to port %d success!rn", port); // Start listening, backlog refers to the maximum length to which the Pending connection queue grows. The queue is full, and a new connection request arrives, the client ECONNREFUSED error. If retransmission is supported, the request is ignored. int backlog = 1; retval = listen(sockfd, backlog); if (retval <0) { printf("listen failed!rn"); CloseTcpSocket(sockfd); return; } printf("listen with %d backlog success!rn ", backlog); int outerFlag = 1; while (outerFlag) { // Accept the client connection, if successful, it will return a socket indicating the connection. The clientAddr parameter will carry the client host and port information; if it fails, return -1 // Get the first connection from the Pending connection queue, create a new socket file description based on the socket protocol, address family, etc. of sockfd, and return. // After that, the receiving and sending are performed on the socket indicating the connection; after that, sockfd can still continue to accept connections from other clients. // The classic concurrency model on the UNIX system is "one process per connection" a child process to handle Connect, the parent process continues to accept connections from other clients // On the Hongmeng liteos-a kernel, you can use the concurrency of UNIX "one process per connection" On top of the model liteos-m kernel, the concurrency model of "one thread per connection" can be used int connfd = -1; connfd = accept(sockfd, (struct sockaddr *)&clientAddr, &clientAddrLen); if ( connfd <0) { printf("accept failed, %d, %drn", connfd, errno); CloseTcpSocket(sockfd); outerFlag = 0; } printf("accept success, connfd = %d !rn", connfd ); // inet_ntoa: The network address is converted to a "." dotted string format. ntohs: The 16-digit number is converted from network byte order to host byte order. printf("client addr info: host = %s, port = %drn", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port)); int innerFlag = 1; // Receive the message and send it back while (innerFlag) { // Subsequent receiving and sending are performed on the socket indicating the connection; // Receive information on the new Socket file description. retval = recv(connfd, request, sizeof(request), 0); if (retval < 0) { printf("recv request failed, %ld!rn", retval); innerFlag = 0; } else if (retval == 0) { // 对方主动断开连接 printf("client disconnected!rn"); innerFlag = 0; } else { printf("recv request{%s} from client done!rn", request); // 发送数据 retval = send(connfd, request, strlen(request), 0); if (retval <= 0) { printf("send response failed, %ld!rn", retval); innerFlag = 0; } printf("send response{%s} to client done!rn", request); // Clear the buffer // Settings Wifi hotspot information memset(&request, 0, sizeof(request)); } DisconnectTcpSocket( connfd ); outerFlag = 0; } CloseTcpSocket(sockfd); } static void TcpServerTask(void *arg) { (void)arg; // First define two Wifi listeners, one for connection change and one for state change WifiEvent eventListener = { .OnWifiConnectionChanged = OnWifiConnectionChanged, .OnWifiScanStateChanged = OnWifiScanStateChanged }; // Wait for 10 system Ticks. How many us per ticks, calculation method = 1000 * 1000 / osKernelGetTickFreq() osDelay(10); // Register the listener WifiErrorCode errCode = RegisterWifiEvent(&eventListener); printf("RegisterWifiEvent: %drn", errCode); WifiDeviceConfig apConfig = {}; strcpy(apConfig.ssid, "MyMobile"); strcpy(apConfig.preSharedKey, "12345678"); apConfig.securityType = WIFI_SEC_TYPE_PSK; int netId = -1; // Enable Wifi errCode = EnableWifi(); printf("EnableWifi: %drn", errCode); osDelay(10); // Set Wifi hotspot configuration information and return the generated network Id-netId. errCode = AddDeviceConfig(&apConfig, &netId); printf("AddDeviceConfig: %drn", errCode); // Connect to Wifi hotspot according to network Id g_connected = 0; errCode = ConnectTo(netId); printf("ConnectTo(%d): %drn", netId, errCode); // If the connection is not completed, wait forever. The g_connected state will be set in the event. while (!g_connected) { printf("g_connected: %drn", g_connected); osDelay(50); } // Start the networking service and find the netif with netifname=wlan0. struct netif* iface = netifapi_netif_find("wlan0"); if (iface) { // Start the DHCP client and get the IP address err_t ret = netifapi_dhcp_start(iface); printf("netifapi_dhcp_start: %drn", ret); // Wait The DHCP server gives feedback to the address osDelay(300); // Execute thread-safe network method, the second parameter is voidFunc, and the third parameter is errFunc. If there is no errFunc, then voidFunc is executed. // netifapi_dhcp_start/netifapi_dhcp_stop, etc. are all called netifapi_netif_common methods. // dhcp_clients_info_show displays information /* server: server_id: 192.168.43.1 mask: 255.255.255.0, 1 gw: 192.168.43.1 T0: 3600 T1: 1800 T2: 3150 clients <1>: mac_idx mac addr state lease tries rto 0 b4c9b9af69f8 192.168.43.56 10 0 1 2 */ ret = netifapi_netif_common(iface, dhcp_clients_info_show, NULL); printf("netifapi_netif_common: %drn", ret); } TcpServerHandler() ; // After networking service ends, disconnect DHCP err_t ret = netifapi_dhcp_stop(iface); printf("netifapi_dhcp_stop: %drn", ret); // Disconnect Wifi hotspot connection Disconnect(); // Remove Wifi hotspot configuration RemoveDevice (netId); // Turn off Wifi errCode = DisableWifi(); printf("DisableWifi: %drn", errCode); osDelay(200); } static void TcpServerEntry(void) { osThreadAttr_t attr; 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-Fail Create"); } } APP_FEATURE_INIT(TcpServerEntry);