asio做tcp的自动拆包时,asio的match condition如何使用的详细说明
首先说点基础概念:因为tcp是流式的,所以如果你自己定制有协议(一般如数据头,命令,数据长度,数据内容,校验), 在tcp下发送你自己的协议的数据包时,就必须要考虑tcp的封包和拆包的问题了。
目前asio使用的人也比较多了吧,我觉得asio对tcp的封包和拆包的支持和设计做的很不错,如果你用asio去做一次对tcp的拆包,会发现真的是相当方便的。
我在asio的基础上包装了一个网络框架asio2(见https://github.com/zhllxt/asio2或https://gitee.com/zhllxt/asio2),里面包含了对TCP数据拆包功能的完整支持(当然内部还是用的asio本身来实现的),按指定的单个字符,按字符串,按用户自定义协议 对数据自动进行拆包,最近发现有些人问起asio的这个自动拆包match condition如何使用的问题,而网上也搜不到match condition的详细使用说明或资料,于是这里写一下,给大家提供点思路。详细代码和说明如下:
using iterator = asio::buffers_iterator<asio::streambuf::const_buffers_type>;
std::pair<iterator, bool> match_role(iterator begin, iterator end)
{
iterator i = begin;
if (end - begin < 4 + 4)
{
return std::pair(begin, false);
}
int head = *(reinterpret_cast<const int*>(i.operator->()));
if (head != 0x01020304)
{
return std::pair(begin, true);
}
i += 4;
int length = *(reinterpret_cast<const int*>(i.operator->()));
if (end - begin - 8 < length)
return std::pair(begin, false);
i += 4;
return std::pair(i + length, true);
}
还有一个比较常见的问题是:使用了match condition后,如果发现接收的数据非法,怎么关闭连接呢?
class match_role
{
public:
explicit match_role(char c) : c_(c) {}
template <typename Iterator>
std::pair<Iterator, bool> operator()(Iterator begin, Iterator end) const
{
Iterator i = begin;
while (i != end)
{
if (*i != c_)
{
session_ptr_->stop();
break;
}
if (*i != c_)
return std::pair(begin, true);
i++;
if (i == end) break;
int length = std::uint8_t(*i);
i++;
if (i == end) break;
if (end - i >= length)
return std::pair(i + length, true);
break;
}
return std::pair(begin, false);
}
void init(std::shared_ptr<asio2::tcp_session>& session_ptr)
{
session_ptr_ = session_ptr;
}
private:
char c_;
std::shared_ptr<asio2::tcp_session> session_ptr_;
};
server.bind_recv([&](auto & session_ptr, std::string_view s)
{
if (s.size() == 0)
{
printf("close illegal client : %s %u\n",
session_ptr->remote_address().c_str(), session_ptr->remote_port());
session_ptr->stop();
return;
}
printf("recv : %u %.*s\n", (unsigned)s.size(), (int)s.size(), s.data());
});
关键词:tcp 自动 封包 拆包 asio match condition role asio2
最后编辑于:2022-11-04
|