在c++中解析基于tcp的TLV协议的问题
Problems parsing a TCP-based TLV protocol in C++
我正在尝试在TCP上实现一个(T)LV协议,从python客户端发送协议缓冲区,并与c++服务器接收。
我的代码看起来差不多是这样的:
char* buffer[RCVBUFSIZE];
int recvsize= 0;
// Filling my buffer with as much as possible.
while(true) {
if(recvsize == RCVBUFSIZE) {
break;
} else if(recvsize+= recv(sock, buffer+recvsize, sizeof(buffer)-recvsize, 0) < 1) {
break;
}
}
//Parsing LV protocol
while(true) {
unsigned short protosize= 0;
//Copy first two bytes into protosize
memcpy((char *) &protosize, buffer, sizeof(unsigned short));
if(protosize == 0) { break; } // Protocol indicates EOM be setting length to "0"
void* protomsg[protosize];
memcpy(protomsg, buffer+sizeof(unsigned short), protosize);
int msglength= sizeof(unsigned short)+protosize;
//Now I'll move the whole buffer to the left so that I don't have to keep track of where I'm at.
memmove(buffer, buffer+msglength, RCVBUFSIZE-msglength);
protoMsg pm;
if(!pm.ParseFromArray(protomsg, protosize)) { break; } // Parsing failed.
// Do stuff with parsed message.
}
现在我有几个问题:
- 接收消息的while循环永不终止。我怀疑当没有任何数据留下时,recv调用阻塞,而我期望它返回一个错误。我已经找到了选择函数来检查是否有东西要读。我会试试的。但是当我只调用一次receive来跳过这个问题时(接收到的消息大约有10个字节,所以我希望在一次调用中收集所有的消息)。我有另一个问题:
- memcpy和memmove似乎没有按预期工作。在第一个循环中,short按预期处理(我在另一端接收到与发送相同的值),但随后协议缓冲区解析的所有内容都失败了。我误解了什么吗?
Edit:关于ntohs的评论—我目前将短消息发送为little-endian,忘记提及。(顺便说一下,我还会改变这个)
第三次编辑:代码现在可以工作了,但我必须更改以下内容:
char* buffer[RCVBUFSIZE];
int recvsize= 0;
// Filling my buffer with as much as possible.
while(true) {
if(recvsize == RCVBUFSIZE) {
break;
} else if((recvsize+= recv(sock, buffer+recvsize, sizeof(buffer)-recvsize, 0)) < 1) {
break;
} else if(recvsize > 1) {
unsigned short msglength= 0;
memcpy((char *) &msglength, buffer+recvsize-sizeof(unsigned short), sizeof(unsigned short));
if(msglength == 0) { break; } // Received a full transmission.
}
}
所以首先我需要在recvsize+= recv()
语句周围添加括号,其次因为非阻塞方法由于某种原因不起作用,我现在检查在读取无符号短数据时传输的最后两个字节是否转换为0。这可能会导致一个问题,如果我读取0碰巧不是长度字段。我可能会开始另一个问题。
我也把protomsg
改为char[]
,但我不认为这真的改变了什么。(我已经解析了一个void数组…)
如果您收到的消息总是在10字节左右,并且RCVBUFSIZE
大于此,则您将永远不会终止,直到读取数据出错。此外,代码中的buffer
变量是一个RCVBUFSIZE
指针数组,这可能不是您想要的。
按如下方式修改代码:
#define MINIMALMESSAGESIZE 10 // Or what the size may be
char buffer[RCVBUFSIZE];
int totalrecvsize= 0;
int recvsize= 0;
while(true) {
if(totalrecvsize >= MINIMALMESSAGESIZE) {
break;
} else if(recvsize= recv(sock, buffer+totalrecvsize, sizeof(buffer)-totalrecvsize, 0) < 1) {
break;
} else {
totalrecvsize += recvsize;
}
}
相关文章:
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 是否可以用"iostream"包装现有的TCP/OOpenSSL会话
- 我可以与 python 服务器而不是 c++ 客户端建立 tcp/ip 套接字吗?
- 提升 Asio TCP 服务器 处理多个客户端
- 通过TCP的PvP通信问题
- C++ boost::asio::ip::tcp::acceptor 有时不接受连接器?
- AWS IoT 开发工具包:通过 TCP 端口 443 使用 MQTT
- 计算出有多少客户端可以连接到我正在使用的一些tcp服务器代码
- 通过单独的 tcp 流建立 http 连接
- 读取 TCP 标头并使用RAW_SOCKET管理 TCP 连接
- C++ TCP 套接字通信 - 连接按预期工作,几秒钟后失败,没有收到新数据,read() 和 recv() 块
- grpc 的 ServerBuilder::AddListeningPort() 总是返回 TCP 端口零
- TCP 服务器的异步读取使用 boost::asio 打印客户端套接字发送的数据
- 如何在没有侦听器的情况下创建 TCP 连接?
- 为什么当通过 TCP 发送的消息速率增加时,请求-响应消息对的延迟会降低?
- C++ TCP 套接字 | 无法将"std::__cxx11::字符串"转换为"const
- C++ "using tcp=x"到"namespace tcp=x"有什么区别
- 在c++中解析基于tcp的TLV协议的问题
- 通过TCP实现TLV协议