HarmonyOS 网络应用开发 原创

小石猛猛冲
发布于 2022-7-24 11:48
浏览
1收藏

@toc

1.UDP客户端

1.1 UDP协议相关API介绍

socket.h接口简介:

这个socket.h中包含声明UDP协议相关接口函数。

接口名 功能描述
socket 创建套接字
sendto 将数据由指定的socket发送到远端主机
recvfrom 从远端主机接收UDP数据
close 关闭套接字

1.2 UDP客户端创建流程介绍

HarmonyOS 网络应用开发-鸿蒙开发者社区

1.3 实现UDP客户端

打开“D3_iot_udp_client”工程的udp_client_demo.c文件,可在代码中查看实现UDP客户端的代码

static void UDPClientTask(void)
{
    //服务器的地址信息
    struct sockaddr_in send_addr;
    socklen_t addr_length = sizeof(send_addr);
    char recvBuf[512];

    //连接Wifi
    WifiConnect("TP-LINK_65A8", "0987654321");

    //创建socket
    if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("create socket failed!\r\n");
        exit(1);
    }

    //初始化预连接的服务端地址
    send_addr.sin_family = AF_INET;
    send_addr.sin_port = htons(_PROT_);
    send_addr.sin_addr.s_addr = inet_addr("192.168.0.175");
    addr_length = sizeof(send_addr);

    //总计发送 count 次数据
    while (1)
    {
        bzero(recvBuf, sizeof(recvBuf));

        //发送数据到服务远端
        sendto(sock_fd, send_data, strlen(send_data), 0, (struct sockaddr *)&send_addr, addr_length);

        //线程休眠一段时间
        sleep(10);

        //接收服务端返回的字符串
        recvfrom(sock_fd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&send_addr, &addr_length);
        printf("%s:%d=>%s\n", inet_ntoa(send_addr.sin_addr), ntohs(send_addr.sin_port), recvBuf);
    }

    //关闭这个 socket
    closesocket(sock_fd);
}

ip地址要改为电脑的ip地址


代码讲解过程见:
https://www.bilibili.com/video/BV1tv411b7SA?p=10&share_source=copy_web&vd_source=8f1cf1d7278a65d1271a6ccbd8891dc6 P25

2.TCP服务端

2.1 TCP协议相关API介绍

socket.h接口简介:

这个socket.h中包含声明TCP协议相关接口函数。

接口名 功能描述
socket 创建套接字
bind 为套接字关联了一个相应的地址与端口号
listen 将套接字设置为监听模式
accept 接受套接字上新的连接
recv 接收数据
send 发送数据
close 关闭套接字

2.2 TCP服务端创建流程介绍

HarmonyOS 网络应用开发-鸿蒙开发者社区

2.3 实现TCP服务端

打开“D4_iot_tcp_server”工程的tcp_server_demo.c文件,可以查看实现TCP服务的代码。

	//创建socket
	if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket is error\r\n");
		exit(1);
	}

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

	//调用bind函数绑定socket和地址
	if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
	{
		perror("bind is error\r\n");
		exit(1);
	}

	//调用listen函数监听(指定port监听)
	if (listen(sock_fd, TCP_BACKLOG) == -1)
	{
		perror("listen is error\r\n");
		exit(1);
	}

	printf("start accept\n");



代码讲解过程见:
https://www.bilibili.com/video/BV1tv411b7SA?p=10&share_source=copy_web&vd_source=8f1cf1d7278a65d1271a6ccbd8891dc6 P26

3.TCP客户端

3.1 TCP协议相关API介绍

socket.h接口简介:
这个socket.h中包含声明TCP协议相关接口函数。

接口名 功能描述
socket 创建套接字
connect 连接到指定的主机
send 发送数据
recv 接收数据
close 关闭套接字

3.2 TCP客户端创建流程介绍

HarmonyOS 网络应用开发-鸿蒙开发者社区

3.3 实现TCP客户端

打开“D3_iot_udp_client”工程的udp_client_demo.c文件,修改部分代码即可实现TCP客户端。

原代码:

static void UDPClientTask(void)
{
    //服务器的地址信息
    struct sockaddr_in send_addr;
    socklen_t addr_length = sizeof(send_addr);
    char recvBuf[512];

    //连接Wifi
    WifiConnect("TP-LINK_65A8", "0987654321");

    //创建socket
    if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("create socket failed!\r\n");
        exit(1);
    }

    //初始化预连接的服务端地址
    send_addr.sin_family = AF_INET;
    send_addr.sin_port = htons(_PROT_);
    send_addr.sin_addr.s_addr = inet_addr("192.168.0.175");
    addr_length = sizeof(send_addr);

    //总计发送 count 次数据
    while (1)
    {
        bzero(recvBuf, sizeof(recvBuf));

        //发送数据到服务远端
        sendto(sock_fd, send_data, strlen(send_data), 0, (struct sockaddr *)&send_addr, addr_length);

        //线程休眠一段时间
        sleep(10);

        //接收服务端返回的字符串
        recvfrom(sock_fd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&send_addr, &addr_length);
        printf("%s:%d=>%s\n", inet_ntoa(send_addr.sin_addr), ntohs(send_addr.sin_port), recvBuf);
    }

    //关闭这个 socket
    closesocket(sock_fd);
}

修改后代码:

static const char *send_data = "Hello! I'm BearPi-HM_Nano TCP Client!\r\n";

static void TCPClientTask(void)
{
    //服务器的地址信息
    struct sockaddr_in send_addr;
    socklen_t addr_length = sizeof(send_addr);
    char recvBuf[512];

    //连接Wifi
    WifiConnect("TP-LINK_65A8", "0987654321");

    //创建socket
    if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("create socket failed!\r\n");
        exit(1);
    }

    //初始化预连接的服务端地址
    send_addr.sin_family = AF_INET;
    send_addr.sin_port = htons(_PROT_);
    send_addr.sin_addr.s_addr = inet_addr("192.168.0.175");
    addr_length = sizeof(send_addr);

    connect(sock_fd,(struct sockaddr *)&send_addr,addr_length)

    //总计发送 count 次数据
    while (1)
    {
        bzero(recvBuf, sizeof(recvBuf));

        //发送数据到服务远端
        send(sock_fd, send_data, strlen(send_data), 0);

        //线程休眠一段时间
        sleep(10);

        //接收服务端返回的字符串
        recv(sock_fd, recvBuf, sizeof(recvBuf), 0);
        printf("%s:%d=>%s\n", inet_ntoa(send_addr.sin_addr), ntohs(send_addr.sin_port), recvBuf);
    }

    //关闭这个 socket
    closesocket(sock_fd);
}

static void TCPClientDemo(void)
{
    osThreadAttr_t attr;

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

APP_FEATURE_INIT(TCPClientDemo);


代码讲解过程见:
https://www.bilibili.com/video/BV1tv411b7SA?p=10&share_source=copy_web&vd_source=8f1cf1d7278a65d1271a6ccbd8891dc6 P27

4. UDP服务端

4.1 UDP协议相关API介绍

socket.h接口简介:
这个socket.h中包含声明UDP协议相关接口函数。

接口名 功能描述
socket 创建套接字
bind 将ip和端口绑定到嵌套字
sendto 将数据由指定的socket发送对方主机
recvfrom 从指定主机接收UDP数据
close 关闭套接字

4.2 UDP服务端创建流程介绍

HarmonyOS 网络应用开发-鸿蒙开发者社区

4.3 实现UDP服务端

打开“D4_iot_tcp_server”工程的tcp_server_demo.c文件,修改部分代码即可实现UDP服务端。

原代码:


static void TCPServerTask(void)
{
	//服务端地址信息
	struct sockaddr_in server_sock;

	//客户端地址信息
	struct sockaddr_in client_sock;
	int sin_size;

	struct sockaddr_in *cli_addr;

	//连接Wifi
	WifiConnect("TP-LINK_65A8", "0987654321");

	//创建socket
	if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket is error\r\n");
		exit(1);
	}

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

	//调用bind函数绑定socket和地址
	if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
	{
		perror("bind is error\r\n");
		exit(1);
	}

	//调用listen函数监听(指定port监听)
	if (listen(sock_fd, TCP_BACKLOG) == -1)
	{
		perror("listen is error\r\n");
		exit(1);
	}

	printf("start accept\n");

	//调用accept函数从队列中
	while (1)
	{
		sin_size = sizeof(struct sockaddr_in);

		if ((new_fd = accept(sock_fd, (struct sockaddr *)&client_sock, (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, &client_sock, sizeof(struct sockaddr));
		}

		//处理目标
		ssize_t ret;

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

			sleep(2);
		}

		close(new_fd);
	}
}


修改后代码:

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

char recvbuf[512];
char *buf = "Hello! I'm BearPi-HM_Nano UDP Server!";

static void UDPServerTask(void)
{
	//服务端地址信息
	struct sockaddr_in server_sock;

	//客户端地址信息
	struct sockaddr_in client_sock;
	int sin_size;

	struct sockaddr_in *cli_addr;

	//连接Wifi
	WifiConnect("TP-LINK_65A8", "0987654321");

	//创建socket
	if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
	{
		perror("socket is error\r\n");
		exit(1);
	}

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

	//调用bind函数绑定socket和地址
	if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
	{
		perror("bind is error\r\n");
		exit(1);
	}

	//调用listen函数监听(指定port监听)
	//if (listen(sock_fd, TCP_BACKLOG) == -1)
	//{
	//	perror("listen is error\r\n");
	//	exit(1);
	//}

	//printf("start accept\n");

	//调用accept函数从队列中
	while (1)
	{
		sin_size = sizeof(struct sockaddr_in);

	//	if ((new_fd = accept(sock_fd, (struct sockaddr *)&client_sock, (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, &client_sock, sizeof(struct sockaddr));
	//	}

		//处理目标
		ssize_t ret;

		while (1)
		{
			if ((ret = recvfrom(sock_fd, recvbuf, sizeof(recvbuf), 0,(struct sockaddr *)&client_sock, (socklen_t *)&sin_size)) == -1)
			{
				printf("recv error \r\n");
			}
			printf("recv :%s\r\n", recvbuf);
			//sleep(2);
			if ((ret = sendto(sock_fd, buf, strlen(buf) + 1, 0,(struct sockaddr *)&client_sock,sizeof(client_sock))) == -1)
			{
				perror("send : ");
			}

			//sleep(2);
		}

		close(new_fd);
	}
}

static void UDPServerDemo(void)
{
	osThreadAttr_t attr;

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

APP_FEATURE_INIT(UDPServerDemo);


代码讲解过程见:
https://www.bilibili.com/video/BV1tv411b7SA?p=10&share_source=copy_web&vd_source=8f1cf1d7278a65d1271a6ccbd8891dc6 P28

5. MQTT客户端

5.1 MQTT介绍

MOTT (Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。

HarmonyOS 网络应用开发-鸿蒙开发者社区


Paho是IBM在2011年建立的Eclipse开源项目,该项目包含以C、Java、Python、Javascript等语言编写的可用客户端。

嵌入式c语言客户端开源地址:
https://github.com/eclipse/paho.mqtt.embedded-c

5.2 Paho MQTT文件目录介绍

HarmonyOS 网络应用开发-鸿蒙开发者社区

  • MQTTClient:封装MQTTPacket生成的高级别C++客户端程序。
  • MQTTClient-C:封装MQTTPacket生成的高级别C客户端程序
    • samples目录提供FreeRTOS和linux两个例程,分别支持FreeRTOS和Linux系统。
    • src目录提供MQTTClient的代码实现能力,以及用于移植到对应平台的网络驱动
  • MQTTPacket:提供MQTT数据包的序列化与反序列化,以及部分辅助函数。

5.3 如何使用Paho MQTT

在MQTTClient.h中包含声明Paho MQTT相关接口函数。

接口名 功能描述
MQTTClientlnit 创建一个客户端对象
MQTTConnect 发送MQTT连接数据包
MQTTConnectWithResults 发送MQTT连接数据包并等待返回
MQTTPublish 发送MQTT发布数据包
MQTTSetMessageHandler 发送每个topic消息处理函数
MQTTSubscribe 发送MQTT订阅数据包
MQTTSubscribeWithResults 发送MQTT订阅数据包并等待返回结果
MQTTUnsubscribe 发送MQTT取消数据包
MQTTDisconnect 发送MQTT断开连接数据包并关闭连接

5.4 实现MQTT客户端

打开“D5_iot_mqtt”工程的iot_mqtt.c文件,查看实现MQTT客户端的代码。

	NetworkConnect(&network, "192.168.0.176", 1883);
	printf("MQTTClientInit  ...\n");
	MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

	MQTTString clientId = MQTTString_initializer;
	clientId.cstring = "bearpi";

	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
  	data.clientID          = clientId;
	data.willFlag          = 0;
	data.MQTTVersion       = 3;
	data.keepAliveInterval = 0;
	data.cleansession      = 1;

	printf("MQTTConnect  ...\n");
	rc = MQTTConnect(&client, &data);
	if (rc != 0) {
		printf("MQTTConnect: %d\n", rc);
		NetworkDisconnect(&network);
		MQTTDisconnect(&client);
		osDelay(200);
		goto begin;
	}

	printf("MQTTSubscribe  ...\n");
	rc = MQTTSubscribe(&client, "substopic", 2, messageArrived);
	if (rc != 0) {
		printf("MQTTSubscribe: %d\n", rc);
		osDelay(200);
		goto begin;
	}
	while (++count)
	{
		MQTTMessage message;
		char payload[30];

		message.qos = 2;
		message.retained = 0;
		message.payload = payload;
		sprintf(payload, "message number %d", count);
		message.payloadlen = strlen(payload);

		if ((rc = MQTTPublish(&client, "pubtopic", &message)) != 0){
			printf("Return code from MQTT publish is %d\n", rc);
			NetworkDisconnect(&network);
			MQTTDisconnect(&client);
			goto begin;
		}
		osDelay(50);	
	}


代码讲解过程见:
https://www.bilibili.com/video/BV1tv411b7SA?p=10&share_source=copy_web&vd_source=8f1cf1d7278a65d1271a6ccbd8891dc6 P29

本部分代码也做了一些更新,如果发现代码不一样的话,可以去gitee同步一下

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-11-23 20:54:25修改
5
收藏 1
回复
举报
回复
    相关推荐