C++ 我需要在这个服务器模型中使用boost::strand吗?
我已经为这个服务器编写代码很长时间了。我正在从多个线程调用io_service::run,但我不确定是否需要在这里使用strand。因为我从不调用async\u多次读取。尽管如果其他连接需要向其他连接发送某些内容,我可能会多次调用async_write。这是我目前掌握的代码C++ 我需要在这个服务器模型中使用boost::strand吗?,c++,boost-asio,C++,Boost Asio,我已经为这个服务器编写代码很长时间了。我正在从多个线程调用io_service::run,但我不确定是否需要在这里使用strand。因为我从不调用async\u多次读取。尽管如果其他连接需要向其他连接发送某些内容,我可能会多次调用async_write。这是我目前掌握的代码 void Session::RecvPacket() { boost::asio::async_read(m_socket, boost::asio::buffer(m_recv_buffer, len),
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()));
}
void会话::RecvPacket()
{
boost::asio::async_read(m_套接字,boost::asio::buffer(m_recv_buffer,len),
boost::bind(&Session::OnRead,this,boost::asio::占位符::error,
boost::asio::占位符::字节(已传输);
}
无效会话::OnRead(const boost::system::错误\u代码和e、大小\u t数据包\u长度、大小\u t字节\u传输)
{
如果(e | |字节_传输!=数据包_长度)
{
如果(e==boost::asio::error::operation\u中止)
返回;
停止();
返回;
}
//做点什么,很可能会寄回一个包
RecvPacket();
}
无效会话::发送数据包(数据包和p)
{
boost::mutex::作用域锁定(send\u mut);
dword len=p.lengh();
m_crypt->makeheader(p.GetRaw().get(),static_cast(len-4));
m_crypt->encrypt(p.GetRaw().get()+4,len-4);
boost::asio::async_write(m_套接字,boost::asio::buffer(p.GetRaw().get(),len),
boost::bind(&Session::OnPacketSend),this,len,boost::asio::placeholders::error,
boost::asio::占位符::传输的字节数,p.GetRaw();
}
我不确定这是不是线程安全。如果只有发送部分不是线程安全的,因为我可以一次发送多个数据包(这将要发生),那么我应该只在那里使用一个数据链吗
Gz是的,您需要一根
钢绞线
如文档中所述,对同一套接字(即共享对象)的并发调用不是线程安全的。但是,在一个对象上挂起多个异步操作是安全的。因此,这是安全的:
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive(...); |
socket.async_write_some(...); |
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive(...); |
| socket.async_write_some(...);
螺纹1 |螺纹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(...);
螺纹1 |螺纹2
--------------------------------------+---------------------------------------
socket.async_receive(…)|
|socket.async_write_some(…);
但这被规定为不安全:
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive(...); | socket.async_write_some(...);
|
螺纹1 |螺纹2
--------------------------------------+---------------------------------------
socket.async_receive(…);|socket.async_write_some(…);
|
此外,Session::SendPacket()
中的send_mut
互斥锁对m_socket
没有真正的安全性。该操作是一个组合操作,由对m_socket.async_write_some()
函数的零个或多个调用组成。由于锁的使用寿命和异步操作的行为,锁不能保证在任何或所有async\u write\u some()
操作期间保持互斥锁
有关螺纹安全和绞线的更多细节,请考虑阅读答案。
另外,请注意,一旦在流上启动了async_write()
操作,程序必须确保在调用初始操作的完成处理程序之前,流上不会发生其他写入操作:
程序必须确保流不执行任何其他写入操作(例如异步写入
、流的异步写入
函数或执行写入的任何其他组合操作),直到此操作完成
如果需要执行多个写入,则考虑排队写入,如答案所示。这种类型的解决方案还可以使管理
数据包对象的底层缓冲区的寿命更容易,因为队列将拥有数据的副本,满足异步写入()
操作的要求,即缓冲区的底层内存块在调用完成处理程序之前保持有效。是,您需要一个链
如文档中所述,对同一套接字(即共享对象)的并发调用不是线程安全的。但是,在一个对象上挂起多个异步操作是安全的。因此,这是安全的:
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive(...); |
socket.async_write_some(...); |
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive(...); |
| socket.async_write_some(...);
螺纹1 |螺纹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(...);
螺纹1 |螺纹2
--------------------------------------+---------------------------------------
socket.async_receive(…)|
|socket.async_write_some(…);
但这被规定为不安全:
thread_1 | thread_2
--------------------------------------+---------------------------------------
socket.async_receive(...); | socket.async_write_some(...);
|
螺纹1 |螺纹2
--------------------------------------+---------------------------------------
socket.async_receive(…);|socket.async_write_some(…);
|
此外,Session::SendPacket()
中的send_mut
互斥锁对m_socket
没有真正的安全性。该操作是一个组合操作,由对m_socket.async_write_some()
函数的零个或多个调用组成。由于锁的使用寿命和异步操作的行为,锁不能保证在任何或所有async\u write\u some()
操作期间保持互斥锁
有关螺纹安全和绞线的更多细节,请考虑阅读答案。
另外,请注意,一旦在流上启动了async_write()
操作,程序必须确保在初始操作完成之前,流上不会发生其他写入操作