How to use Hongmeng Hi3861 to complete Wifi hotspot connection and start TCP SocketServer?

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

How to use Hongmeng Hi3861 to complete Wifi hotspot connection and start TCP SocketServer?  How to use Hongmeng Hi3861 to complete Wifi hotspot connection and start TCP SocketServer?

2. TcpClient (network debugging assistant) connects to the TcpServer (HiBurn) of the development board.

How to use Hongmeng Hi3861 to complete Wifi hotspot connection and start TCP SocketServer?  How to use Hongmeng Hi3861 to complete Wifi hotspot connection and start TCP SocketServer?How to use Hongmeng Hi3861 to complete Wifi hotspot connection and start TCP SocketServer?  How to use Hongmeng Hi3861 to complete Wifi hotspot connection and start TCP SocketServer?

3. TcpClient inputs data and sends it, and TcpServer receives it and sends it back to TcpClient.

How to use Hongmeng Hi3861 to complete Wifi hotspot connection and start TCP SocketServer?  How to use Hongmeng Hi3861 to complete Wifi hotspot connection and start TCP SocketServer?How to use Hongmeng Hi3861 to complete Wifi hotspot connection and start TCP SocketServer?  How to use Hongmeng Hi3861 to complete Wifi hotspot connection and start TCP SocketServer?

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);

Guess you like

Origin blog.csdn.net/yaxuan88521/article/details/113929210