繁体   English   中英

我需要在此服务器模型中使用boost :: strand吗?

[英]Do I need to use a boost::strand in this server model?

我已经为这个服务器编码了一段时间了。 我正在从1个以上的线程中调用io_service :: run,但是我不确定是否需要在这里使用strand。 由于我从未多次调用async_read。 虽然如果其他连接需要向其他人发送内容,则我可能多次调用async_write。 这是我到目前为止的代码

void Session::RecvPacket()
{
    boost::asio::async_read(m_socket, boost::asio::buffer(m_recv_buffer, len),
        boost::bind(&Session::OnRead, this, boost::asio::placeholders::error,
        boost::asio::placeholders::bytes_transferred));

}

void Session::OnRead(const boost::system::error_code &e, size_t packet_length, size_t bytes_transferred)
{
    if (e || bytes_transferred != packet_length)
    {
        if (e == boost::asio::error::operation_aborted)
            return;

        Stop();
        return;
    }

    // do something and most likely send a packet back

    RecvPacket();
}
void Session::SendPacket(packet &p)
{
    boost::mutex::scoped_lock lock(send_mut);

    dword len = p.Lenght(); 

    m_crypt->makeheader(p.GetRaw().get(), static_cast<word>(len - 4));
    m_crypt->encrypt(p.GetRaw().get() + 4, len - 4);

    boost::asio::async_write(m_socket, boost::asio::buffer(p.GetRaw().get(), len),
        boost::bind(&Session::OnPacketSend, this, len, boost::asio::placeholders::error,
        boost::asio::placeholders::bytes_transferred, p.GetRaw()));
}

我不确定这是否是线程安全的。 如果仅发送部分不是线程安全的,因为我可以一次发送多个数据包(这将要发生),我是否应该仅在其中使用链?

GZ

是的,您需要strand

tcp::socket文档中所述,同一套接字(即共享对象)上的并发调用不是线程安全的。 但是,在一个对象上进行多个异步操作是安全的。 因此,这是安全的:

thread_1                             | thread_2
--------------------------------------+---------------------------------------
socket.async_receive(...);            |
socket.async_write_some(...);         |

这是安全的:

thread_1                             | thread_2
--------------------------------------+---------------------------------------
socket.async_receive(...);            |
                                      | socket.async_write_some(...);

但这被指定为不安全:

thread_1                             | thread_2
--------------------------------------+---------------------------------------
socket.async_receive(...);            | socket.async_write_some(...);
                                      |

此外, Session::SendPacket()send_mut互斥量不能为m_socket提供真正的安全性。 , made up of zero or more call's to the m_socket.async_write_some() function. boost::asio::async_write()操作是一个 ,由对m_socket.async_write_some()函数的零个或多个调用 由于锁的寿命和异步操作的行为,该锁不能保证在任何或所有async_write_some()操作期间都将保持互斥锁。

有关线程安全和线束的更多详细信息,请考虑阅读答案。


另外,请注意,一旦在流上启动了async_write()操作,程序必须确保在调用初始操作的完成处理程序之前,不会在流上发生其他写操作:

程序必须确保该流完成之前,该流不执行其他任何写操作(例如async_write ,流的async_write_some函数或任何其他执行写操作的组合操作)。

如果需要执行多次写入,请考虑对写入进行排队, 如此答案所示。 这种类型的解决方案还可以使管理packet对象的基础缓冲区的寿命变得更加容易,因为队列将拥有数据的副本,满足async_write()操作的要求,即缓冲区的基础内存块在调用完成处理程序之前一直保持有效。 。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM