【发布时间】:2011-12-06 23:15:52
【问题描述】:
这是我的实现:
- 客户端 A 为客户端 B 发送消息
- 服务器通过
async_read处理消息适量的数据和 将等待来自客户端 A 的新数据(为了不阻止客户端 A) - 之后服务器会处理信息(可能做一个mysql
查询),然后使用
async_write将消息发送给客户端B。
问题是,如果客户端 A 发送消息的速度非常快,async_writes 将在调用之前的 async_write 处理程序之前交错。
有没有简单的方法可以避免这个问题?
编辑 1: 如果客户端 C 在客户端 A 之后向客户端 B 发送消息,则应该会出现相同的问题...
编辑 2: 这行得通吗?因为好像挡住了,不知道在哪里……
namespace structure {
class User {
public:
User(boost::asio::io_service& io_service, boost::asio::ssl::context& context) :
m_socket(io_service, context), m_strand(io_service), is_writing(false) {}
ssl_socket& getSocket() {
return m_socket;
}
boost::asio::strand getStrand() {
return m_strand;
}
void push(std::string str) {
m_strand.post(boost::bind(&structure::User::strand_push, this, str));
}
void strand_push(std::string str) {
std::cout << "pushing: " << boost::this_thread::get_id() << std::endl;
m_queue.push(str);
if (!is_writing) {
write();
std::cout << "going to write" << std::endl;
}
std::cout << "Already writing" << std::endl;
}
void write() {
std::cout << "writing" << std::endl;
is_writing = true;
std::string str = m_queue.front();
boost::asio::async_write(m_socket,
boost::asio::buffer(str.c_str(), str.size()),
boost::bind(&structure::User::sent, this)
);
}
void sent() {
std::cout << "sent" << std::endl;
m_queue.pop();
if (!m_queue.empty()) {
write();
return;
}
else
is_writing = false;
std::cout << "done sent" << std::endl;
}
private:
ssl_socket m_socket;
boost::asio::strand m_strand;
std::queue<std::string> m_queue;
bool is_writing;
};
}
#endif
【问题讨论】:
-
请注意,异步写入的价值远低于异步读取。大多数写入实际上是即时的,因为操作系统将在本地缓冲数据。另一方面,读取可能会阻止等待远程端,而您在本地对此无能为力。因此,同步写入是实现排序的一种可行方式。这也解决了数据所有权的问题——上面的代码是不正确的,因为
str在write()返回时被销毁,这可能在boost::asio_async_write()访问缓冲区之前。
标签: c++ asynchronous boost-asio