El código simple realiza la función de cliente MQTT

El flujo de trabajo del protocolo MQTT es el siguiente:


De hecho, es muy sencillo, es decir, el cliente publica y suscribe temas al servidor para realizar la interacción de información. Aquí usaré código simple para realizar las funciones del cliente.

Instalación del servidor MQTT

Aquí uso Raspberry Pi como servidor, y el servidor instalado es mosquitto.
El proceso de instalación es muy sencillo.

sudo apt-get update #获取更新
sudo apt-get install mosquitto #安装mosquitto服务器
mosquitto -v #启动mosquitto服务器

Simplemente ingrese los códigos anteriores uno por uno. Por supuesto, también puede instalarlos en otros lugares, como máquinas virtuales o computadoras. El siguiente sitio web tiene paquetes de instalación de mosquitto y direcciones de descarga de software tutorial en diferentes entornos
.

Captura de simulación por computadora

Después de instalar el servidor, debe analizar la siguiente comunicación entre el cliente y el servidor. Primero, busque una computadora para instalar un software de cliente MQTT. Aquí instalé MQTT.fx. Hay muchos recursos en Internet para el paquete de instalación. Puede encontrarlo usted mismo, baje y abra el software, siga los pasos para ingresar al siguiente contenido, donde el puerto predeterminado del servidor es 1883, por lo que debe configurarse en 1883.


Luego abra wireshark. Cuando esté listo, haga clic en conectar en el software MQTT.fx para comenzar a capturar paquetes. Si no conoce el software wireshark, puede consultar uno de mis artículos.

Wireshark captura el blog-CSDN de packages_yuansec
A través de los paquetes capturados, se encuentra que el protocolo MQTT se basa en el protocolo TCP/IP.La acción del cliente para conectarse al servidor es primero un apretón de manos de tres vías tcp y luego envía un comando de solicitud de conexión.


Continúe capturando paquetes, cree una nueva versión y envíela al servidor. Se envía el nivel QoS0 utilizado aquí. Se puede ver que el envío es muy simple, solo un mensaje. A partir de los datos analizados, se puede ver que este mensaje contiene el asunto y el contenido


A continuación, cree una nueva suscripción y tome el mensaje


Finalmente, publique nuevamente, puede ver que los datos se envían a la suscripción y, al mismo tiempo, puede ver el proceso de interacción de datos en el mensaje capturado.

Código

Aquí implemento la función de cliente en la máquina virtual, entorno linux
Primero, siga los pasos de ahora, primero realice la conexión sock y realice el protocolo de enlace de tres vías de tcp

int connect_sock()
{	
	int sock;
	struct sockaddr_in aa;
	
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if(sock == -1)
    	{
		printf("sock error\n");
		return -1;
	}
	
	aa.sin_family = AF_INET;
	aa.sin_port = htons(1883);
	aa.sin_addr.s_addr = inet_addr("192.168.0.10");
	
	if(connect(sock, (struct sockaddr *)&aa, sizeof(aa)) < 0)
	{
		printf("connect error\n");
		return -1;
	}
	printf("connect with destination host...\n");
	
	return sock;
}

A continuación, la solicitud de conexión MQTT, aquí se refiere al formato de la captura de paquetes, define directamente cada byte

int connect_pub(int fd)
{
	char data[1024];
	data[0] = 0x10;
	data[1] = 14;
	data[2] = 0x00;
	data[3] = 0x04;
	data[4] = 'M';
	data[5] = 'Q';
	data[6] = 'T';
	data[7] = 'T';
	
	data[8] = 4;
	data[9] = 2;
	
	data[10] = 0x00;
	data[11] = 0x3c;
	
	data[12] = 0x00;
	data[13] = 0x02;
	
	data[14] = 'f';
	data[15] = 'e';

	int sum = send(fd, data, 16, 0);
	if(sum < 0)
	{
		printf("send error\n");
		return -1;
	}
	printf("connect_pub send sum = %d\n",sum);
	
	return 0;
}

El siguiente paso es establecer una conexión de suscripción.

int connect_sub(int fd, char *topic)
{
	char data[1024];
	int i;
	data[0] = 0x82;
	
	data[2] = 0x00;
	data[3] = 0x03;

	int len = strlen(topic);
	data[4] = len/256;
	data[5] = len%256;
	for(i = 0; i < len; i++)
		data[6 + i] = topic[i];
		
	data[6 + len] = 0x00;
	data[1] = 5 + len;

	int sum = send(fd, data, 7 + len, 0);
	if(sum < 0)
	{
		printf("send error\n");
		return -1;
	}
	printf("connect_sub send sum = %d\n",sum);
	
	return 0;
}

Una vez que se establece la conexión de suscripción, se puede publicar el contenido y, al mismo tiempo, se crea un hilo para recibir los datos enviados por el servidor.

int pub(int fd, char *topic, char *str)
{
	char data[1024];
	int i;
	
	data[0] = 0x30;
	
	int t_len = strlen(topic);
	data[2] = t_len/256;
	data[3] = t_len%256;
	
	for(i = 0; i < t_len; i++)
		data[4 + i] = topic[i];
		
	int s_len = strlen(str);
	for(i = 0; i < s_len; i++)
		data[4 + t_len + i] = str[i];
	
	data[1] = 2 + t_len + s_len;	
	
	int sum = send(fd, data, 4 + t_len + s_len, 0);
	if(sum < 0)
	{
		printf("send error\n");
		return -1;
	}
	//printf("pub sum = %d\n",sum);
	
	return 0;
}

struct msg
{
	int fd;
	char *topic; 
};
void *sub_rev(struct msg *msg_sub)
{
	char data[1024];
	char str[1024];

	while(1)
	{
		int num = recv(msg_sub->fd, data, 1024, 0);
		if(num < 0)
		{
			printf("recv error\n");
			return 0;
		}
		if(num > 0)
		{
			if(data[0] == 0x30)
			{
				int len = data[2]*256 + data[3];
				if(strncmp(data + 4, msg_sub->topic, len) == 0)
				{
					strncpy(str, data + 4 + len, num - 4 - len);
					printf("recv data:%s\n", str);
					memset(data, '\0', strlen(data));
					memset(str, '\0', strlen(str));
				}
				
			}
		}
	}
}

lograr efecto

Aquí el nombre del tema es fijo, puede definir el tema usted mismo en la aplicación real, puede ver que el efecto se realiza

código completo

Finalmente, hay un código de desconexión, no lo completaré aquí, el principio es el mismo

#include<stdio.h>
#include<sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

int connect_sock()
{	
	int sock;
	struct sockaddr_in aa;
	
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if(sock == -1)
    	{
		printf("sock error\n");
		return -1;
	}
	
	aa.sin_family = AF_INET;
	aa.sin_port = htons(1883);
	aa.sin_addr.s_addr = inet_addr("192.168.0.10");
	
	if(connect(sock, (struct sockaddr *)&aa, sizeof(aa)) < 0)
	{
		printf("connect error\n");
		return -1;
	}
	printf("connect with destination host...\n");
	
	return sock;
}

int connect_pub(int fd)
{
	char data[1024];
	data[0] = 0x10;
	data[1] = 14;
	data[2] = 0x00;
	data[3] = 0x04;
	data[4] = 'M';
	data[5] = 'Q';
	data[6] = 'T';
	data[7] = 'T';
	
	data[8] = 4;
	data[9] = 2;
	
	data[10] = 0x00;
	data[11] = 0x3c;
	
	data[12] = 0x00;
	data[13] = 0x02;
	
	data[14] = 'f';
	data[15] = 'e';

	int sum = send(fd, data, 16, 0);
	if(sum < 0)
	{
		printf("send error\n");
		return -1;
	}
	printf("connect_pub send sum = %d\n",sum);
	
	return 0;
}
int connect_sub(int fd, char *topic)
{
	char data[1024];
	int i;
	data[0] = 0x82;
	
	data[2] = 0x00;
	data[3] = 0x03;

	int len = strlen(topic);
	data[4] = len/256;
	data[5] = len%256;
	for(i = 0; i < len; i++)
		data[6 + i] = topic[i];
		
	data[6 + len] = 0x00;
	data[1] = 5 + len;

	int sum = send(fd, data, 7 + len, 0);
	if(sum < 0)
	{
		printf("send error\n");
		return -1;
	}
	printf("connect_sub send sum = %d\n",sum);
	
	return 0;
}
int pub(int fd, char *topic, char *str)
{
	char data[1024];
	int i;
	
	data[0] = 0x30;
	
	int t_len = strlen(topic);
	data[2] = t_len/256;
	data[3] = t_len%256;
	
	for(i = 0; i < t_len; i++)
		data[4 + i] = topic[i];
		
	int s_len = strlen(str);
	for(i = 0; i < s_len; i++)
		data[4 + t_len + i] = str[i];
	
	data[1] = 2 + t_len + s_len;	
	
	int sum = send(fd, data, 4 + t_len + s_len, 0);
	if(sum < 0)
	{
		printf("send error\n");
		return -1;
	}
	//printf("pub sum = %d\n",sum);
	
	return 0;
}

struct msg
{
	int fd;
	char *topic; 
};
void *sub_rev(struct msg *msg_sub)
{
	char data[1024];
	char str[1024];

	while(1)
	{
		int num = recv(msg_sub->fd, data, 1024, 0);
		if(num < 0)
		{
			printf("recv error\n");
			return 0;
		}
		if(num > 0)
		{
			if(data[0] == 0x30)
			{
				int len = data[2]*256 + data[3];
				if(strncmp(data + 4, msg_sub->topic, len) == 0)
				{
					strncpy(str, data + 4 + len, num - 4 - len);
					printf("recv data:%s\n", str);
					memset(data, '\0', strlen(data));
					memset(str, '\0', strlen(str));
				}
				
			}
		}
	}
}

int main()
{
	int sock;	
	char topic[1024] = "test";
	char str[1024];
	
	sock = connect_sock();
	
	if(sock < 0)
	{
		printf("connect_sock error\n");
		return 0;
	}
	if(connect_pub(sock) < 0)
	{
		printf("connect_pub error\n");
		return 0;
	}
	if(connect_sub(sock, topic) < 0)
	{
		printf("connect_sub error\n");
		return 0;
	}
	
	
	pthread_t sub_id;
	struct msg sub_msg;
	sub_msg.fd = sock;
	sub_msg.topic = topic;
	pthread_create(&sub_id, NULL, (void*)*sub_rev, &sub_msg);
	usleep(100 * 1000);
	
	while(1)
	{
		printf("please input message:");
		fgets(str, 1024, stdin);
		pub(sock, topic, str);
		memset(str, '\0', strlen(str));
		usleep(100 * 1000);
	}
	
	
	close(sock);
	
}

Supongo que te gusta

Origin blog.csdn.net/lhh2333/article/details/127301721
Recomendado
Clasificación