同一个 socket 的 async_write 操作,其内部是通过 async_write_some 来实际执行的。在上一次写操作的 WriteDone 回调触发之前,如果再次调用 async_write,就会导致发送的 stream 顺序错乱。典型的复现场景如下:

boost::asio::async_write(socket, buffer(xxx, 1024000), yield[ec]);
boost::asio::async_write(socket, buffer(buf, 32), std::bind(&Session::write, this, std::placeholders::_1, std::placeholders::_2));

客户端收到的数据就会乱掉。

解决方案

添加发送队列即可解决这个问题:

void CAsioSession4S::HandleWriteDone(const boost::system::error_code &ec)
{
	if (this->_sending != nullptr)
	{
		delete this->_sending;
		this->_sending = nullptr;
	}
	//error will disconnected
	if (ec)
	{
		while (!_sendQueue.empty())
		{
			delete _sendQueue.front();
			_sendQueue.pop();
		}
		this->Disconnect();
		return;
	}
	//检查发送队列
	if (!_sendQueue.empty())
	{
		this->_sending = _sendQueue.front();
		_sendQueue.pop();
		boost::asio::async_write((*_socket.get()), this->_sending->send, std::bind(&CAsioSession4S::HandleWriteDone, this->shared_from_this(), std::placeholders::_1));
	}
}