如何管理协议中的消息结尾?我使用msgpack-c,我找到的唯一解决方案是在有效载荷之前发送报头(单独)。
将标头发送到客户端:
// header
{
"message_type": "hello",
"payload_size": 10
}
客户端接收报头,对其进行解包,并分配一个缓冲区"0";payload_ size";,从流中接收数据,如果缓冲区已完成,则消息完成。
我想简洁地发送标题和正文
{
"header": { "message_type":"hello", "payload_size": 10},
"payload": {...} // can come in multiple frame
}
我的问题是,我不知道是否可以在接收完整消息之前部分解包报头以了解大小(由于libevent限制,如果>4096kb则拆分)
你会怎么做?我对所有解决方案持开放态度。
C++
使用unpack()函数
您可以使用unpack()函数的offset
参数。看见https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_unpacker#client-控制器-缓冲器
下面是一个代码示例:
#include <iostream>
#incluee <msgpack.hpp>
int main() {
msgpack::sbuffer buf;
msgpack::pack(buf, std::make_tuple("first message", 123, 56.78));
msgpack::pack(buf, std::make_tuple("second message", 42));
std::size_t off = 0; // cursor of buf
{
// unpack() function starts parse from off (0)
auto oh = msgpack::unpack(buf.data(), buf.size(), off);
// off is updated to 25. 25 is MessagePack formatted byte size
// of ["first message",123,56.78]
// (I use JSON notation but actual format is MessagePack)
std::cout << "off:" << off << std::endl;
std::cout << *oh << std::endl;
}
{
// unpack() function starts parse from off (25)
auto oh = msgpack::unpack(buf.data(), buf.size(), off);
// off is updated to 42.
// 42 - 25 = 17. 17 is MessagePack formatted byte size
// of ["second message",42]
// (I use JSON notation but actual format is MessagePack)
std::cout << "off:" << off << std::endl;
std::cout << *oh << std::endl;
}
}
输出为
off:25
["first message",123,56.78]
off:42
["second message",42]
msgpack-c unpack()在内部管理缓冲区的位置。你不需要通过payload_size
。
此外,您可以在缓冲区中混合非消息包格式的数据。
+--------------------+-----------------------------+--------------------+
| MessagePackBytes1 | Any format user knows size | MessagePackBytes2 |
+--------------------+-----------------------------+--------------------+
假设用户知道包含MessgePackBytes1(未知大小)、任何格式的数据(已知大小)和MessgePackBytes1(未知尺寸)的数据结构。
#include <iostream>
#incluee <msgpack.hpp>
int main() {
msgpack::sbuffer buf;
msgpack::pack(buf, std::make_tuple("first message", 123, 56.78));
std::string non_mp = "non mp format data";
buf.write(non_mp.data(), non_mp.size());
msgpack::pack(buf, std::make_tuple("second message", 42));
std::size_t off = 0; // cursor of buf
{
auto oh = msgpack::unpack(buf.data(), buf.size(), off);
std::cout << "off:" << off << std::endl;
std::cout << *oh << std::endl;
}
{
std::string extracted{buf.data() + off, non_mp.size()};
std::cout << extracted << std::endl;
off += non_mp.size();
}
{
auto oh = msgpack::unpack(buf.data(), buf.size(), off);
std::cout << "off:" << off << std::endl;
std::cout << *oh << std::endl;
}
}
输出为
off:25
["first message",123,56.78]
non mp format data
off:60
["second message",42]
使用解包器
它有点先进,但可能适合流媒体用例。https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_unpacker#msgpack-缓冲器控制下面是一个从连续和分散的接收消息中拆包MessagePack的例子。https://github.com/msgpack/msgpack-c/blob/700167995927f0348fb08ae2579440c1bc135480/example/boost/asio_send_recv.cpp#L41-L64
C
C版本与C++基本相似。
使用unpack()函数
C版本具有类似的解包功能。这是原型:
msgpack_unpack_return
msgpack_unpack_next(msgpack_unpacked* result,
const char* data, size_t len, size_t* off);
您可以传递off
作为偏移量,类似于C++版本。C没有引用,因此需要使用&off
传递off
的地址。看见https://github.com/msgpack/msgpack-c/wiki/v2_0_c_overview#using-解压缩功能
如果您想知道诸如stiring之类的单个可变长度字段大小,您可以访问解包对象的size
成员变量。例如:
typedef struct {
uint32_t size;
struct msgpack_object* ptr;
} msgpack_object_array;
typedef struct {
uint32_t size;
const char* ptr;
} msgpack_object_str;
typedef struct {
uint32_t size;
const char* ptr;
} msgpack_object_bin;
typedef struct {
int8_t type;
uint32_t size;
const char* ptr;
} msgpack_object_ext;
请参阅https://github.com/msgpack/msgpack-c/wiki/v2_0_c_overview#object
使用解包器
请参阅https://github.com/msgpack/msgpack-c/wiki/v2_0_c_overview#using-拆包