C++从MQTT读取字节数组写入图片报错求助
问题描述
尝试在C++中从MQTT读取图片二进制字节数组并写入对应格式(PNG/JPEG)的文件,但写入后的图片无法打开,报错:
Error interpreting JPEG image file(improper call to JPEG library in state 201)
测试用发布端Python代码
更新:按照建议使用publish.single,结果依旧。
import paho.mqtt.client as mqtt f=open("/home/anup/Documents/img_2.jpg", "rb") # 同目录下3.7kiB的文件 fileContent = f.read() byteArr = bytearray(fileContent) broker_address="0.0.0.0" client = mqtt.Client("P1") # 创建新实例 client.connect(broker_address, 1883) # 连接到 broker res = client.publish("in",byteArr) # 发布消息 client.loop() print(res)
import paho.mqtt.publish as publish publish.single("in", payload=byteArr, hostname="localhost", port=1883)
订阅端C++代码
使用aschiffler/cpp-mqtt仓库的MQTT库,通过Ninja编译:
// 引入Mosquitto MQTT库及其他标准库 #include <mqtt/client.h> // Mosquitto客户端 #include <ostream> // std::cout #include <string> #include <cstring> #include <cstdlib> #include <unistd.h> #include <fstream> int main() { // 定义broker地址(本地1883端口) std::string ip = "localhost:1883"; // 定义客户端ID std::string id = "consumer"; // 使用MQTT V5构造客户端 mqtt::client client(ip, id, mqtt::create_options(MQTTVERSION_5)); // 连接到broker client.connect(); // 订阅主题"in" client.subscribe("in"); // 启动消息消费循环 client.start_consuming(); bool running = true; while (running) { // 存储消息指针 mqtt::const_message_ptr messagePointer; // 尝试消费消息 if (client.try_consume_message(&messagePointer)) { // 将payload转为字符串 std::string messageString = messagePointer -> get_payload_str(); // 打印payload到控制台(调试用) std::cout << messageString << std::endl; std::string filename = "/home/anup/Documents/mqtt/cpp-mqtt/image.jpg"; std::ofstream outfile(filename, std::ios::binary); outfile.write((char*)messageString.c_str(), sizeof(messageString)); outfile.close(); // 收到"quit"则退出循环 if (messageString == "quit") { running = false; } } } return 0; }
订阅端控制台输出(截断)
�Y,���àyPà�U���ٳ�F��!*�G9�6dD������xr��é�ì�Tm塦d��˨�TKGj��W�5��6'��nvK��W�D��۩(ځf՛��6��˲p� �V�+°��?)°27M���̴I��R�������8��/;����<�ì�DB�����5�u^�M�j�ò��K���U��gg��QF�/3%����MЮ��W��8_���d�0j£�"�OX�R���mm�K��K�E4H���L�� ���w��F;�'���8�9�O �� �S)M��é���-ĜBxcP���§-� ֆ����9��+><$?�g�Rf��+a6��1R���.� e��d��O�ù����� ��Y�_�h�.X�i�mù����W��x�9eG�v3é��T:�����1Z� �n�����7�_�$G7���ù W)Wn�=�R���z�è��uè�XZ*(ø�>F���$�B&��h�>�e�;Ҩ�x�d�aò�?��y��՛�è�nҕ�����5���jI�^ç��/e���a� ��a�òm�N*�߀U��5.<���8z:A��ӍZ��&V§��.�IEND�Bù�
问题原因与修复
核心问题
- 二进制转字符串丢失数据:图片二进制数据中可能包含
\0(空字符),使用get_payload_str()转为std::string时,会将\0视为字符串结束符,导致后续字节被截断,写入文件的数据不完整。 - 写入长度错误:
sizeof(messageString)获取的是std::string对象本身的内存大小,不是存储的字节长度,导致写入的字节数错误。
修复后的C++代码
直接处理原始二进制payload,避免转字符串:
#include <mqtt/client.h> #include <ostream> #include <string> #include <fstream> int main() { std::string ip = "localhost:1883"; std::string id = "consumer"; mqtt::client client(ip, id, mqtt::create_options(MQTTVERSION_5)); client.connect(); client.subscribe("in"); client.start_consuming(); bool running = true; while (running) { mqtt::const_message_ptr messagePointer; if (client.try_consume_message(&messagePointer)) { // 获取原始二进制payload auto payload = messagePointer->get_payload(); const char* data = payload.data(); size_t data_len = payload.size(); // 打印接收数据长度(调试用) std::cout << "Received data length: " << data_len << std::endl; std::string filename = "/home/anup/Documents/mqtt/cpp-mqtt/image.jpg"; std::ofstream outfile(filename, std::ios::binary); // 写入完整二进制数据 outfile.write(data, data_len); outfile.close(); // 单独判断quit命令 if (data_len == 4 && std::string(data, 4) == "quit") { running = false; } } } return 0; }
修复说明
- 使用
get_payload()获取mqtt::binary类型的原始二进制数据,直接通过data()和size()访问完整字节内容,避免空字符截断问题。 - 写入文件时使用实际数据长度
data_len,确保所有字节都被写入。 - 处理
quit命令时,单独提取前4个字节转为字符串判断,不干扰二进制图片数据的处理。
内容的提问来源于stack exchange,提问作者Explorer
相关产品推荐
相关产品推荐

