c-使用msgpack知道协议中的消息结束



如何管理协议中的消息结尾?我使用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-拆包

最新更新