关于 protobuf 在网络传输中数据丢失问题解决方案
2023-09-14 09:09:11 时间
如上。
排查过程:
syntax = "proto3";
message login_request{
fixed32 id = 1;
fixed32 pwd = 2;
}
message login_reply{
fixed32 errno_id = 1;
fixed32 money = 2;
}
#include <stdio.h>
#include "msg.pb.h"
#include <string>
using namespace std;
int main()
{
login_request lrs,reply;
lrs.set_id(12345678);
lrs.set_pwd(12345678);
string str = lrs.SerializeAsString();
reply.ParseFromString(str);
printf("id:%d\n",reply.id());
printf("pwd:%d\n",reply.pwd());
return 0;
}
确定问题不是出在protobuf这边之后,那就只能是网络传输过程或者传输前后的字符串转化过程中出现问题了。
#include <stdio.h>
#include "msg.pb.h"
#include <string>
using namespace std;
int main()
{
login_request lrs,reply;
lrs.set_id(12345678);
lrs.set_pwd(12345678);
string str = lrs.SerializeAsString();
const char *c = str.c_str();
string str2 = c;
reply.ParseFromString(str2);
printf("id:%d\n",reply.id());
printf("pwd:%d\n",reply.pwd());
return 0;
}
这时候pwd已经为0了,数据发生了丢失。但是id依旧正常。
猜测是长度问题,因为早上解决另一个问题的时候再Stack Overflow上有人说要带上包长度。
于是:
#include <stdio.h>
#include "msg.pb.h"
#include <string>
using namespace std;
int main()
{
login_request lrs,reply;
lrs.set_id(12345678);
lrs.set_pwd(12345678);
string str = lrs.SerializeAsString();
const char *c = str.c_str();
string str2;
str2.assign(c,str.length());
reply.ParseFromString(str2);
printf("id:%d\n",reply.id());
printf("pwd:%d\n",reply.pwd());
return 0;
}
至此实验结束,让我们再看看为什么会这样.
#include <stdio.h>
#include "msg.pb.h"
#include <string>
using namespace std;
int main()
{
login_request lrs,reply;
lrs.set_id(12345678);
lrs.set_pwd(12345678);
string str = lrs.SerializeAsString();
const char *c = str.c_str();
string str2;
string str3 = c;
str2.assign(c,str.length());
reply.ParseFromString(str2);
printf("id:%d\n",reply.id());
printf("pwd:%d\n",reply.pwd());
printf("str.length():%d\n",str.length());
printf("str2.length():%d\n",str2.length());
printf("str3.length():%d\n",str3.length());
printf("c.length():%d\n",strlen(c)); //4
return 0;
}
结果可自行验证。当你决定使用 const char* 的时候,你就已经放弃了长度信息。
一定要用const char *吗?
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
不然这个函数为什么要我们输入一个 len?好玩吗?
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
至此,问题解决。
相关文章
- BAT-使用BAT方法判断网络启动EXE(快捷方式)
- 【黑马Android】(05)短信/查询和添加/内容观察者使用/子线程网络图片查看器和Handler消息处理器/html查看器/使用HttpURLConnection采用Post方式请求数据/开源项目
- OS开发网络篇—数据缓存
- iOS开发之网络数据解析--中文输出
- iOS开发之网络数据解析(二)--XML解析简介
- 【刷题】面筋-网络-数据传输方式
- centos8平台用ss监控网络
- iOS中 UIWebView加载网络数据 技术分享
- iOS网络编程-ASIHTTPRequest小例子-数据请求队列
- 【刷题】面筋-网络-数据传输方式
- socket网络编程【python】
- 【YOLOv8/YOLOv7/YOLOv5/YOLOv4/Faster-rcnn系列算法改进NO.61】结合最新的CVPR2023年Fasternet网络模块
- atitit.二进制数据无损转字符串网络传输
- 内容分发网络 CDN 体系中原始服务器 Original Server 的定义
- flutter 每次获取网络数据后都要setState刷新全局变量
- CV之OD之YOLOv3:深度学习之计算机视觉神经网络Yolov3-5clessses训练自己的数据集全程记录
- 基于PSO优化的LSTM网络数据预测matlab仿真
- 【Tensorflow+Keras】keras实现条件生成对抗网络DCGAN--以Minis和fashion_mnist数据集为例
- 【网络数据采集】python爬取豆瓣top250电影目录
- m基于DCAR编码感知的网络路由发现算法matlab仿真
- Kubernetes中的网络策略
- 三层楼100人办公网络如何规划设计实施开通并验收交付使用(实战案例)