我正在尝试boost asio,测试代码基于asio-wrapper。
在这种情况下,有没有办法在不依赖std::this_thread::sleep_for
的情况下防止数据集中?
这是测试代码:
#include<iostream>
#include <vector>
#include<thread>
#include<chrono>
#include "asio_wrapper.hpp"
class WritableHandlerImplServer : public cppeng::tcp::WritableHandler {
public:
void HandleCallback(std::vector<uint8_t> data,
std::shared_ptr<cppeng::tcp::Writable> writable) override {
// Convert void pointer to string
std::string received(data.begin(), data.end());
std::cout << "Server Rx: " << received << std::endl;
}
void NotifyClosed(std::shared_ptr<cppeng::tcp::Writable> ptr) override {
std::cout << "Server: Connection closed!" << std::endl;
}
};
class WritableHandlerImplClient : public cppeng::tcp::WritableHandler {
public:
void HandleCallback(std::vector<uint8_t> data,
std::shared_ptr<cppeng::tcp::Writable> writable) override {
// Convert void pointer to string
std::string received(data.begin(), data.end());
std::cout << "Client Rx: " << received << std::endl;
rx_flag_ = true;
}
void NotifyClosed(std::shared_ptr<cppeng::tcp::Writable> ptr) override {
std::cout << "Client: Connection closed!" << std::endl;
}
bool rx_flag_{ false };
};
int main()
{
/*this is a test code*/
try {
WritableHandlerImplServer writable_handler_server;
WritableHandlerImplClient writable_handler_client;
cppeng::tcp::Server server(3000, writable_handler_server);
server.Start();
cppeng::tcp::Client client("127.0.0.1", 3000, writable_handler_client);
client.Start(1000);
client.Write("abcd");
std::this_thread::sleep_for(std::chrono::milliseconds(5));
client.Write("efgh");
std::this_thread::sleep_for(std::chrono::milliseconds(5));
client.Write("ijkl");
std::this_thread::sleep_for(std::chrono::milliseconds(5));
client.Write("mnop");
std::this_thread::sleep_for(std::chrono::milliseconds(5));
client.Write("qrst");
std::this_thread::sleep_for(std::chrono::milliseconds(5));
client.Write("uvwx");
std::this_thread::sleep_for(std::chrono::milliseconds(5));
client.Write("yz");
server.Stop();
client.Stop();
}
catch (std::exception& e) {
std::cout << "exception :" << e.what() << "\n";
}
return EXIT_SUCCESS;
}
写/读功能:
void Connection::DoRead() {
auto self(shared_from_this());
boost::asio::async_read(socket_,
boost::asio::buffer(read_buffer_.data(), read_buffer_.size()),
boost::asio::transfer_at_least(1),
[this, self](std::error_code ec, std::size_t length) {
if (!ec) {
std::vector<uint8_t> rx_data(read_buffer_.begin(), read_buffer_.begin() + length);
writable_handler_.HandleCallback(std::move(rx_data), shared_from_this());
DoRead();
} else {
Close();
}
});
}
void Connection::DoWrite() {
auto self(shared_from_this());
boost::asio::async_write(socket_,
boost::asio::buffer(write_queue_.front().data(),
write_queue_.front().size()),
[this, self](std::error_code ec, std::size_t /*length*/) {
if (!ec) {
write_queue_.pop();
if (!write_queue_.empty()) {
DoWrite();
} else {
write_busy_ = false;
}
} else {
Close();
}
});
}
更新:
源代码作者以这样的方式实现了 Package 器写函数,如果boost::asio写函数正在忙碌,第二条消息就会丢失!
void Connection::Write(const std::string &data) {
// Add the data to the queue
write_queue_.emplace(data.begin(), data.end());
// Start the write process only if we are not already busy writing
if (!write_busy_) {
write_busy_ = true;
DoWrite();
}
else {
}
}
1条答案
按热度按时间niknxzdl1#
假设“数据集中”是指数据包不代表“消息”:是的。TCP是一种流协议。你得到一个逻辑流。数据流在线路上传输的方式无关紧要。
您需要使用应用程序协议来了解如何解析流。通常会有信息的框架。常用的选择是分隔符(例如,NUL字节)或长度前缀消息。
在你的例子中,看起来消息可能是4个八位字节,这意味着你可以
transfer_exactly(4)
。如果没有,我建议使用NULL定界符(当然,选择一个不会干扰实际消息内容的分隔符)。看起来asio_wrapper没有提供实现这一点的方法。它只会在框架不重要的情况下帮助你,或者你必须做额外的缓冲和解析,这会使你的处理程序变得复杂。
我建议不要使用 Package :
Live On Coliru
印刷