HarmonyOS网络编程 --TCP服务端开发

参考网上连老师的TCP自己整理一套TCP服务端的开发,整体思路大概如下:
1、TCP服务首先需要连接WiFi,采用的是STA模式,在编写TCP服务端代码之前已经对WiFi功能进行了学习,代码也编写好了,所以直接封装一下拿来使用就OK!!代码如下,在applications/sample/wifi-iot/app/下新建wifi_demo文件夹,然后新建wifi_sta_connect.h文件和wifi_sta_connect.c文件:

wifi_sta_connect.h

#ifndef _WIFI_STA_CONNECT_H
#define _WIFI_STA_CONNECT_H

        
extern int g_connected;
//WIFI sta模式相关功能函数
void PrintLinkedInfo(WifiLinkedInfo* info);
void OnWifiConnectionChanged(int state, WifiLinkedInfo* info);
void OnWifiScanStateChanged(int state, int size);

#endif

wifi_sta_connect.c

#include <stdio.h>
#include <string.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 "wifi_sta_connect.h"

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: %s\r\n",
        macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid);
}

int g_connected = 0;
void OnWifiConnectionChanged(int state, WifiLinkedInfo* info)
{
    if (!info) return;

    printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state);
    PrintLinkedInfo(info);

    if (state == WIFI_STATE_AVALIABLE) {
        g_connected = 1;
    } else {
        g_connected = 0;
    }
}

void OnWifiScanStateChanged(int state, int size)
{
    printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size);
}

2、WiFi功能模块封装的相对简单,后期如果需要更多的功能,在模块中添加即可,接下来就是TCP服务端代码的编写,其中需要调用WiFi功能。
在applications/sample/wifi-iot/app下新建socket_demo文件夹,然后添加tcp_server_test.c文件
tcp_server_test.c

#include <stdio.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifi_device.h"
#include "lwip/api_shell.h"

#include "hi_wifi_api.h"
#include "lwip/ip_addr.h"
#include "lwip/netifapi.h"

#include "lwip/sockets.h"
#include "wifi_sta_connect.h"

#define SERVER_PORT_TCP			6666
#define TCP_BACKLOG 10


/* 在sock_fd 进行监听,在 new_fd 接收新的链接 */
int sock_fd, new_fd;

char recvbuf[512];
char *buf = "hello! I'm server!";

int tcp_server_demo(void){
    /* 自己的地址信息 */
	struct sockaddr_in my_addr;
	/*	连接者的地址信息*/
	struct sockaddr_in their_addr;
	int sin_size;

	struct sockaddr_in *cli_addr;

    printf("%s %d \r\n", __FILE__, __LINE__);

    /* 1 、创建socket  */
	if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
        printf("%s %d \r\n", __FILE__, __LINE__);
		perror("socket is error\r\n");
		exit(1);
	}

    /* 主机字节顺序 */
	/* 协议 */
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(6666);//设置你的端口号
	/* 当前IP 地址写入 */
	my_addr.sin_addr.s_addr = INADDR_ANY;

	/* 将结构体其余的都清零 */
	bzero(&(my_addr.sin_zero), 8);

    printf("%s %d \r\n", __FILE__, __LINE__);
	/* bind 绑定*/
	if(bind(sock_fd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
	{
        printf("%s %d \r\n", __FILE__, __LINE__);
		perror("bind is error\r\n");
		exit(1);
	}

    printf("%s %d \r\n", __FILE__, __LINE__);
	/* 开始监听 */
	if(listen(sock_fd, TCP_BACKLOG) == -1)
	{
		perror("listen is error\r\n");
		exit(1);
	}

    printf("%s %d \r\n", __FILE__, __LINE__);
	printf("start accept\n");

    /* accept() 循环 */
	while(1)
	{
		sin_size = sizeof(struct sockaddr_in);

        printf("%s %d \r\n", __FILE__, __LINE__);
		if((new_fd = accept(sock_fd, (struct sockaddr *)&their_addr, (socklen_t *)&sin_size)) == -1)
		{
			perror("accept");
			continue;
		}

		cli_addr = malloc(sizeof(struct sockaddr));

		printf("accept addr\r\n");

		if(cli_addr != NULL)
		{
			memcpy(cli_addr, &their_addr, sizeof(struct sockaddr));
		}

		//处理目标
		ssize_t ret;
		

		while(1)
		{
            printf("%s %d \r\n", __FILE__, __LINE__);
			if((ret = recv(new_fd, recvbuf, sizeof(recvbuf), 0)) == -1){
				printf("recv error \r\n");
				return -1;
			}
			printf("recv :\r\n");
			printf("%s", recvbuf);
			printf("\r\n");
			sleep(2);
			if((ret = send(new_fd, buf, strlen(buf) + 1, 0)) == -1)
			{
				perror("send : ");
			}

			sleep(2);
		}

		

		close(new_fd);

        return 0;
	}
}

void start_sta_mode(void){ 
    WifiErrorCode errCode;
    WifiEvent eventListener = {
        .OnWifiConnectionChanged = OnWifiConnectionChanged,  //连接状态改变
        .OnWifiScanStateChanged = OnWifiScanStateChanged     //扫描状态变化
    };
    WifiDeviceConfig apConfig = {};
    int netId = -1;

    osDelay(10);
    errCode = RegisterWifiEvent(&eventListener); //注册wifi事件的回调函数
    printf("RegisterWifiEvent: %d\r\n", errCode);

    // setup your AP params
    strcpy(apConfig.ssid, "*******");  //设置你的wifi名称
    strcpy(apConfig.preSharedKey, "*******");  //设置你的wifi密码
    apConfig.securityType = WIFI_SEC_TYPE_PSK;

    while (1) {
        errCode = EnableWifi();  //打开wifi设备的sta模式,使其可以扫描
        printf("EnableWifi: %d\r\n", errCode);
        osDelay(10);

        errCode = AddDeviceConfig(&apConfig, &netId);  //增加WIFI设备的配置,分配得到一个net id保存在netId中
        printf("AddDeviceConfig: %d\r\n", errCode);

        g_connected = 0;
        errCode = ConnectTo(netId);
        printf("ConnectTo(%d): %d\r\n", netId, errCode);

        while (!g_connected) {
            osDelay(10);
        }
        printf("g_connected: %d\r\n", g_connected);
        osDelay(50);

        // 联网业务开始
        struct netif* iface = netifapi_netif_find("wlan0");
        if (iface) {
            err_t ret = netifapi_dhcp_start(iface);
            printf("netifapi_dhcp_start: %d\r\n", ret);

            osDelay(200); // wait DHCP server give me IP
            ret = netifapi_netif_common(iface, dhcp_clients_info_show, NULL);
            printf("netifapi_netif_common: %d\r\n", ret);
        }

        // 模拟一段时间的联网业务
        // int timeout = 60;
        while (1) {
            // osDelay(100);
            // printf("after %d seconds, I'll disconnect WiFi!\n", timeout);
            printf("ongoing Iot business\n");
            uint32_t result = tcp_server_demo();
            if (result==0)
            {
                /* code */
                printf("I'll disconnect WiFi!\n");
                break;
            }
            
        }

        // 联网业务结束
        err_t ret = netifapi_dhcp_stop(iface);
        printf("netifapi_dhcp_stop: %d\r\n", ret);

        Disconnect(); // disconnect with your AP

        RemoveDevice(netId); // remove AP config

        errCode = DisableWifi();
        printf("DisableWifi: %d\r\n", errCode);
        osDelay(200);
    }
}



void TcpServerTask(void* arg){
    (void) arg;
    start_sta_mode();
    // tcp_server_demo();

}

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(TcpServerTask, NULL, &attr) == NULL) {
        printf("[WifiConnectDemo] Falied to create TcpServerTask!\n");
    }
}

SYS_RUN(TcpServerEntry);

在applications/sample/wifi-iot/app下新建socket_demo文件夹,然后添加BUILD.gn文件,这里需要把封装WiFi功能模块的文件包含进去:
BUILD.gn

static_library("socket_demo") {
    sources = [
        "tcp_server_test.c",
    ]

    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/components/cmsis/2.0",
        "//base/iot_hardware/interfaces/kits/wifiiot_lite",
        "//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
        "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
        "//foundation/communication/wifi_lite/interfaces/wifiservice",
        "//applications/sample/wifi-iot/app/wifi_demo",
    ]
}

3、最后修改applications/sample/wifi-iot/app/BUILD.gn文件:

import("//build/lite/config/component/lite_component.gni")

lite_component("app") {

    features = [

        "wifi_demo",

        "socket_demo",

    ]

}

4、最后编译烧录即可,自己可以编写一个TCP客户端去连接服务端进行测试,作为学习HarmonyOS的新手,还有许多不足,欢迎大家留言补充,共同学习成长!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值