左边同时启动了5个客户端,右边上面是server收界面client消息,右下方是mqtt subscruib 窗口。
本文的实现参考了几篇很不错的博客,下面列出给大家参考:
这是一个聊天室程序,实现多个客户端向一个服务端发送消息,服务端输入消息,可以向所有连接上的客户端广播。
https://blog.csdn.net/zouli415/article/details/79696766
https://blog.csdn.net/xqhrs232/article/details/51202118
https://blog.csdn.net/usstmiracle/article/details/103050652
https://blog.csdn.net/qq_43260665/article/details/88541433
使用多线程实现了client断开重连。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFFER_SIZE 1024
bool need_reconnect = false;
//int main(int argc, const char * argv[])
int client_connect(void)
{
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(11332);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//server_addr.sin_addr.s_addr = inet_addr("192.168.232.153");
bzero(&(server_addr.sin_zero), 8);
//创建套接字
int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(server_sock_fd == -1)
{
perror("socket error");
return 1;
}
char recv_msg[BUFFER_SIZE];
char input_msg[BUFFER_SIZE];
//连接服务器
if(connect(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) == 0)
{
fd_set client_fd_set;
struct timeval tv;
while(1)
{
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&client_fd_set);
FD_SET(STDIN_FILENO, &client_fd_set);
//FD_SET(server_sock_fd, &client_fd_set);
//select(server_sock_fd += 1, &client_fd_set, NULL, NULL, &tv);
if(FD_ISSET(STDIN_FILENO, &client_fd_set))
{
bzero(input_msg, BUFFER_SIZE);
//fgets(input_msg, BUFFER_SIZE, stdin);
strcpy(input_msg,"123456789 hello this test message Good news!!!!!!!!!!!");
//向服务端发送消息
if(send(server_sock_fd, input_msg, BUFFER_SIZE, 0) == -1)
{
perror("Client send message error due to socket server program shutdown!\n");
need_reconnect = true;
return 0;
}
need_reconnect = false;
}
if(FD_ISSET(server_sock_fd, &client_fd_set))
{
bzero(recv_msg, BUFFER_SIZE);
//接收来自服务端的消息
long byte_num = recv(server_sock_fd, recv_msg, BUFFER_SIZE, 0);
if(byte_num > 0)
{
if(byte_num > BUFFER_SIZE)
{
byte_num = BUFFER_SIZE;
}
recv_msg[byte_num] = '\0';
printf("服务器:%s\n", recv_msg);
}else if(byte_num < 0)
{
printf("接受消息出错!\n");
}else
{
printf("服务器端退出!\n");
exit(0);
}
}
}
}
return 0;
}
void reconnect()
{
int count =0;
while(1)
{
if(need_reconnect)
{
client_connect();
int left_time = (5-count);
printf("reconnect 10s 1 times,left time: %d",left_time);
count++;
}
sleep(10);
if(count>4)
{
break;
}
}
return;
}
int main(int argc, const char * argv[])
{
std::thread th1(client_connect);
std::thread th2(reconnect);
th1.detach();
th2.join();
return 0;
}
#include
#include
#include
#include
#include
#include
#include
//mqtt head file
#include "MQTTAsync.h"
#include
#include
#define BACKLOG 5 //完成三次握手但没有accept的队列的长度
#define CONCURRENT_MAX 8 //应用层同时可以处理的连接
#define SERVER_PORT 11332
#define BUFFER_SIZE 1024
#define QUIT_CMD ".quit"
//mqtt define
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "clientPub"
#define TOPIC "MQTT xxx"
//#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
volatile MQTTAsync_token deliveredtoken;
int finished = 0;
bool is_connect = false;
long byte_num =0;
//socket
int client_fds[CONCURRENT_MAX];
char input_msg[BUFFER_SIZE];
char recv_msg[BUFFER_SIZE];
int rsu_server()
{
std::mutex my_mutex;
//本地地址
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bzero(&(server_addr.sin_zero), 8);
//创建socket
int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(server_sock_fd == -1)
{
perror("socket error");
return 1;
}
//绑定socket
int bind_result = bind(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(bind_result == -1)
{
perror("bind error");
return 1;
}
//listen
if(listen(server_sock_fd, BACKLOG) == -1)
{
perror("listen error");
return 1;
}
//fd_set
fd_set server_fd_set;
int max_fd = server_sock_fd;
struct timeval tv; //超时时间设置
while(1)
{
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&server_fd_set);
//add standard input
FD_SET(STDIN_FILENO, &server_fd_set);
if(max_fd 0)
{
int index = -1;
for(int i = 0; i < CONCURRENT_MAX; i++)
{
if(client_fds[i] == 0)
{
index = i;
client_fds[i] = client_sock_fd;
break;
}
}
if(index >= 0)
{
printf("新RSU客户端(%d)加入成功 %s:%d\n", index, inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));
}
else
{
bzero(input_msg, BUFFER_SIZE);
strcpy(input_msg, "服务器加入的RSU客户端数达到最大值,无法加入!\n");
send(client_sock_fd, input_msg, BUFFER_SIZE, 0);
printf("客户端连接数达到最大值,新RSU客户端加入失败 %s:%d\n", inet_ntoa(client_address.sin_addr), ntohs(client_address.sin_port));
}
}
}
for(int i =0; i < CONCURRENT_MAX; i++)
{
if(client_fds[i] !=0)
{
if(FD_ISSET(client_fds[i], &server_fd_set))
{
//处理某个RSU客户端过来的消息-------------
bzero(recv_msg, BUFFER_SIZE);
//std::lock_guard lguard(my_mutex);
byte_num = recv(client_fds[i], recv_msg, BUFFER_SIZE, 0);
if (byte_num > 0)
{
if(byte_num > (BUFFER_SIZE-4))
{
byte_num = (BUFFER_SIZE-4);
}
recv_msg[byte_num++] = 'E';
recv_msg[byte_num++] = 'N';
recv_msg[byte_num++] = 'D';//添加消息的结尾标志
recv_msg[byte_num] = '\0';
printf("RSU(%d):%s\n", i, recv_msg);
}else if(byte_num < 0)
{
printf("从RSU(%d)接受消息出错.\n", i);
} else
{
FD_CLR(client_fds[i], &server_fd_set);
client_fds[i] = 0;
printf("RSU客户端(%d)退出了\n", i);
}
}
}
}
}
}
return 0;
}
//mqtt code -----------------------------------------------------
void connlost(void *context, char *cause)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
int rc;
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
printf("Reconnecting\n");
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
finished = 1;
}
}
void onDisconnect(void* context, MQTTAsync_successData* response)
{
printf("Successful disconnection\n");
finished = 1;
}
void onSend(void* context, MQTTAsync_successData* response)
{
//MQTTAsync client = (MQTTAsync)context;
//MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer;
//int rc;
printf("Message with token value %d delivery confirmed\n", response->token);
//opts.onSuccess = onDisconnect;
//opts.context = client;
/*
if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start sendMessage, return code %d\n", rc);
exit(EXIT_FAILURE);
}
*/
}
void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
printf("Connect broker failed, rc %d\n", response ? response->code : 0);
finished = 1;
}
void onConnect(void* context, MQTTAsync_successData* response)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
int rc;
printf("Successful connection\n");
is_connect = true;
/* opts.onSuccess = onSend;
opts.context = client;
pubmsg.payload = (void*)PAYLOAD;
pubmsg.payloadlen = (int)strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
deliveredtoken = 0;
if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start sendMessage, return code %d\n", rc);
exit(EXIT_FAILURE);
}
*/
}
int wuxi_server()
{
std::mutex mqtt_mutex;
MQTTAsync client;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
int rc;
char test_msg[100]="RSU client message is not arrived.This is the test information, please ignore it.";
MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
MQTTAsync_setCallbacks(client, NULL, connlost, NULL, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.onSuccess = onConnect;
conn_opts.onFailure = onConnectFailure;
conn_opts.context = client;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Waiting for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
recv_msg, TOPIC, CLIENTID);
while(!is_connect)
{
//printf("sleep\n");
usleep(100000L);
}
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
opts.onSuccess = onSend;
opts.context = client;
while(1)
{
int rc;
//printf("while1\n");
//#define MQTTAsync_message_initializer
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
//pubmsg.payload = (void*)PAYLOAD;
if(byte_num > 2)
{
pubmsg.payload = (void*)recv_msg;
pubmsg.payloadlen = (int)strlen(recv_msg);
}else{
pubmsg.payload = (void*)test_msg;
pubmsg.payloadlen = (int)strlen(test_msg);
usleep(2000000L); //(1ms = 1000us) Send 1 times 2 second
}
pubmsg.qos = QOS;
pubmsg.retained = 0;
deliveredtoken = 0;
if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start sendMessage, return code %d\n", rc);
exit(EXIT_FAILURE);
}
std::lock_guard lguard(mqtt_mutex);
memset(recv_msg,0,sizeof(recv_msg));
byte_num = 0;
//usleep(20000L);//Send 50 times a second
usleep(100000L);
}
while (!finished)
#if defined(WIN32)
Sleep(100);
#else
usleep(10000L);
#endif
MQTTAsync_destroy(&client);
return rc;
}
int main(int argc, const char * argv[])
{
std::thread th1(rsu_server);
std::thread th2(wuxi_server);
th1.detach();
th2.detach();
while(1)
{
#if defined(WIN32)
Sleep(100);
#else
usleep(1000000L);
#endif
}
return 0;
}
#include
#include
#include
#include "MQTTAsync.h"
#include
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "WXClientSub"
#define TOPIC "MQTT YC2WX"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
volatile MQTTAsync_token deliveredtoken;
int disc_finished = 0;
int subscribed = 0;
int finished = 0;
void connlost(void *context, char *cause)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
int rc;
printf("\nConnection lost\n");
if (cause)
printf(" cause: %s\n", cause);
printf("Reconnecting\n");
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
finished = 1;
}
}
int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message)
{
int i;
char* payloadptr;
printf("Message arrived\n");
printf(" topic: %s\n", topicName);
printf(" message: ");
payloadptr = (char*)message->payload;
for(i=0; ipayloadlen; i++)
{
putchar(*payloadptr++);
}
putchar('\n');
MQTTAsync_freeMessage(&message);
MQTTAsync_free(topicName);
return 1;
}
void onDisconnect(void* context, MQTTAsync_successData* response)
{
printf("Successful disconnection\n");
disc_finished = 1;
}
void onSubscribe(void* context, MQTTAsync_successData* response)
{
printf("Subscribe succeeded\n");
subscribed = 1;
}
void onSubscribeFailure(void* context, MQTTAsync_failureData* response)
{
printf("Subscribe failed, rc %d\n", response ? response->code : 0);
finished = 1;
}
void onConnectFailure(void* context, MQTTAsync_failureData* response)
{
printf("Connect failed, rc %d\n", response ? response->code : 0);
finished = 1;
}
void onConnect(void* context, MQTTAsync_successData* response)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
int rc;
printf("Successful connection\n");
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
"Press Q to quit\n\n", TOPIC, CLIENTID, QOS);
opts.onSuccess = onSubscribe;
opts.onFailure = onSubscribeFailure;
opts.context = client;
deliveredtoken = 0;
if ((rc = MQTTAsync_subscribe(client, TOPIC, QOS, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start subscribe, return code %d\n", rc);
exit(EXIT_FAILURE);
}
}
int main(int argc, char* argv[])
{
MQTTAsync client;
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
int rc;
int ch;
MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
MQTTAsync_setCallbacks(client, client, connlost, msgarrvd, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.onSuccess = onConnect;
conn_opts.onFailure = onConnectFailure;
conn_opts.context = client;
if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
while (!subscribed)
#if defined(WIN32)
Sleep(100);
#else
usleep(10000L);
#endif
if (finished)
goto exit;
do
{
ch = getchar();
} while (ch!='Q' && ch != 'q');
disc_opts.onSuccess = onDisconnect;
if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start disconnect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
while (!disc_finished)
#if defined(WIN32)
Sleep(100);
#else
usleep(10000L);
#endif
exit:
MQTTAsync_destroy(&client);
return rc;
}