【MQTT协议使用总结】基于-FreeRTOS平台-移植MQTT协议栈

news/2024/12/22 2:05:05/

文章目录

  • 仓库地址
  • 关键接口适配
    • FreeRTOS_read
    • FreeRTOS_write
    • NetworkInit && NetworkConnect && NetworkDisconnect
  • 总结

仓库地址

https://github.com/eclipse/paho.mqtt.embedded-c

在这里插入图片描述
这里官方给了一些平台适配案例,这里参考FreeRTOS的

关键接口适配

使用使用了lwip的一些接口

FreeRTOS_read

int FreeRTOS_read(Network* n, unsigned char* buffer, int len, int timeout_ms)
{// 将超时时间转换为 timeval 结构体表示的时间间隔struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000};// 如果超时时间小于等于 0,将超时时间设置为 0.1 秒(100 微秒)if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0)) {interval.tv_sec = 0;interval.tv_usec = 100;}fd_set read_fds;// 初始化文件描述符集合,清空 read_fdsFD_ZERO(&read_fds);// 将网络结构体中的套接字加入到文件描述符集合中,表示关注该套接字的可读事件FD_SET(n->my_socket, &read_fds);int bytes = 0;while(bytes < len) {// 使用 lwip_select 等待套接字可读事件,设置超时时间为 intervalint result = lwip_select(n->my_socket + 1, &read_fds, NULL, NULL, &interval);// 如果返回值小于等于 0,表示没有可读事件发生或者发生错误,跳出循环if (result <= 0)break;// 套接字可读int rc = lwip_recv(n->my_socket, &buffer[bytes], (len - bytes), 0);// 如果接收返回值为 -1,表示接收出错if (rc == -1) {// 如果错误不是 EAGAIN(资源暂时不可用)或 EWOULDBLOCK(操作会阻塞)if (errno!= EAGAIN && errno!= EWOULDBLOCK)bytes = -1;break;}// 如果接收返回值为 0,表示连接已关闭else if (rc == 0) {bytes = 0;break;}// 如果接收成功,更新已接收的字节数elsebytes += rc;}return bytes;
}

FreeRTOS_write

int FreeRTOS_write(Network* n, unsigned char* buffer, int len, int timeout_ms)
{TickType_t xTicksToWait = timeout_ms / portTICK_PERIOD_MS; /* convert milliseconds to ticks */TimeOut_t xTimeOut;int sentLen = 0;int flags = 0;vTaskSetTimeOutState(&xTimeOut); /* Record the time at which this function was entered. */do {int rc = 0;// 设置 lwip_send 为非阻塞方式flags = MSG_DONTWAIT;rc = lwip_send(n->my_socket, buffer + sentLen, len - sentLen, flags);if (rc > 0)sentLen += rc;else if (rc == 0 || (rc < 0 && errno == EAGAIN)) {// 缓冲区已满,等待一段时间再尝试发送vTaskDelay(pdMS_TO_TICKS(10)); // 延时10ms再尝试发送} else if (rc < 0) {sentLen = rc;break;}} while (sentLen < len && xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE);return sentLen;
}

NetworkInit && NetworkConnect && NetworkDisconnect

// 初始化网络结构体
void NetworkInit(Network* n)
{// 将套接字初始化为无效值n->my_socket = -1;// 设置网络结构体的读取函数指针为 FreeRTOS_readn->mqttread = FreeRTOS_read;// 设置网络结构体的写入函数指针为 FreeRTOS_writen->mqttwrite = FreeRTOS_write;
}// 连接到指定地址和端口
int NetworkConnect(Network* n, char* addr, int port)
{// 打开连接并获取套接字描述符n->my_socket = transport_open((int8_t*)addr, port);// 如果套接字描述符有效(不等于 -1),表示连接成功if (-1!= n->my_socket) {return 0;}// 连接失败,返回 -1return -1;
}// 断开网络连接
void NetworkDisconnect(Network* n)
{// 如果套接字描述符有效(大于 0)if (n->my_socket > 0 ) {// 关闭套接字closesocket(n->my_socket);// 将套接字描述符重置为无效值n->my_socket = -1;}
}
int32_t transport_open(int8_t* servip, int32_t port)
{int32_t *sock = &mysock;int32_t ret;int32_t opt;struct sockaddr_in addr;// 初始化服务器信息memset(&addr, 0, sizeof(addr));addr.sin_len = sizeof(addr);addr.sin_family = AF_INET;// 填写服务器端口号addr.sin_port = PP_HTONS(port);// 填写服务器 IP 地址addr.sin_addr.s_addr = inet_addr((const char*)servip);// 创建套接字*sock = socket(AF_INET, SOCK_STREAM, 0);// 连接服务器ret = connect(*sock, (struct sockaddr*)&addr, sizeof(addr));if(ret!= 0){// 连接失败,关闭链接close(*sock);// 返回 -1 表示连接失败return -1;}// 连接成功,设置 TCP_NODELAY 选项(禁用 Nagle 算法)opt = 1;setsockopt(*sock, IPPROTO_TCP, TCP_NODELAY, (void *)&opt, sizeof(int));// 返回套接字描述符return *sock;
}

总结

实际使用过程中,遇到了lwip阻塞的阻塞情况,注意采用非阻塞方式进行读取。


http://www.ppmy.cn/news/1527434.html

相关文章

C++学习笔记----7、使用类与对象获得高性能(二)---- 理解对象生命周期(1)

对象的生命周期包含三个活动&#xff1a;生成&#xff0c;解体&#xff0c;与赋值。理解如何以及什么时候生成、解体以及赋值对象&#xff0c;以及如何客户化其行为非常重要。 1、对象生成 对象在声明的时候生成&#xff08;如果是在栈上的话&#xff09;&#xff0c;或者显式…

打造民国风格炫酷个人网页:用HTML和CSS3传递民国风韵

附源码&#xff01;&#xff01;&#xff01; 感谢支持 小弟不断创作网站demo感兴趣的可以关注支持一下 对了 俺在结尾带上了自己用的 背景 大家可以尝试换一下效果更好哦~~~ 如何创建一个民国风格的炫酷网页 在这篇博客中&#xff0c;我们将展示如何制作一个结合民国风格和…

python植物大战僵尸项目源码【免费】

植物大战僵尸是一款经典的塔防游戏&#xff0c;玩家通过种植各种植物来抵御僵尸的进攻。 源码下载地址&#xff1a; 植物大战僵尸项目源码 提取码: 8muq

避免 PyCharm 将该 Python 脚本作为测试运行

为了避免 PyCharm 将该 Python 脚本作为测试运行&#xff08;即 pytest 自动捕获&#xff09;&#xff0c;你可以做以下几步来确保该脚本作为普通的 Python 程序执行&#xff0c;而不是作为 pytest 运行。 解决方案&#xff1a; 1. 确保文件名不以 test_ 开头&#xff1a; P…

electron有关mac构建

针对 Mac M1/2/3 芯片的设备&#xff0c;proces.archarm64. 执行下面命令&#xff0c;检查下按照的 node.js 版本是不是 intel x64 指令集&#xff0c;如果是的话安装下 arm64 指令集的 node.js终端中执行以下命令&#xff1a;node -p process.arch 对应的node版本也是arm版 …

区块链领航者孙宇晨:驾驭潮流,共绘未来新篇章

​区块链技术的迅速发展正在重塑全球经济格局&#xff0c;而孙宇晨&#xff0c;作为这一变革的先锋人物之一&#xff0c;以其卓越的远见和创新能力在行业内引领潮流&#xff0c;开创了区块链未来的新局面。 孙宇晨的名字与区块链技术密不可分。作为波场TRON的创始人&#xff0c…

9.11 QT ( Day 4)

一、作业 1.Widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimerEvent> //定时器类 #include <QTime> #include <QtTextToSpeech> //文本转语音类QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEcl…

游戏、网关等服务借助Docker容器化并使用Kubernetes部署、更新等

本文首发在这里 请先看完 实现负责消息转发、推送的网关服务负责网络、定时、坐下、站起、重连等&#xff0c;支持多类游戏的无锁房间 Docker容器化 Build and Push docker build -t panshiqu/game_server:latest -t panshiqu/game_server:1 -t panshiqu/game_server:1.0 -…