关于一般网络编程中的写缓冲区
-
11-09-2019 - |
题
我正在使用 boost.asio 编写服务器。我为每个连接都有读写缓冲区,并使用异步读/写功能(async_write_some
/ async_read_some
).
带有读缓冲区和 async_read_some
, , 这里没有问题。只是调用 async_read_some
函数没问题,因为读取缓冲区仅在读取处理程序中读取(通常意味着在同一线程中)。
但是,写缓冲区需要从多个线程访问,因此需要锁定以进行修改。
第一个问题!
有什么办法可以避免写入缓冲区的 LOCK 吗?
我将自己的数据包写入堆栈缓冲区并将其复制到写入缓冲区。然后,致电 async_write_some
发送数据包的函数。这样,如果我串行发送两个数据包,可以调用 async_write_some
函数两次?
第二个问题!
socket编程中异步写入的常用方式是什么?
谢谢阅读。
解决方案
答案#1:
您是正确的,锁定是一个可行的办法,但有一个更简单的方法来做到这一切。升压在ASIO一个可爱的小结构称为strand
。已使用的链包的任何回调都会被序列化,保证,无论哪个线程执行回调。基本上,它处理任何锁定为您服务。
这意味着,你可以有很多作家,只要你想,如果他们都通过的相同链包裹(所以,共享中所有的作家,你的单股),他们将串行执行。有一点需要注意的是,以确保您不尝试使用相同的实际缓存在内存中完成所有的写操作。例如,这是为了避免什么:
char buffer_to_write[256]; // shared among threads
/* ... in thread 1 ... */
memcpy(buffer_to_write, packet_1, std::min(sizeof(packet_1), sizeof(buffer_to_write)));
my_socket.async_write_some(boost::asio::buffer(buffer_to_write, sizeof(buffer_to_write)), &my_callback);
/* ... in thread 2 ... */
memcpy(buffer_to_write, packet_2, std::min(sizeof(packet_2), sizeof(buffer_to_write)));
my_socket.async_write_some(boost::asio::buffer(buffer_to_write, sizeof(buffer_to_write)), &my_callback);
有,你分享你的实际写入缓冲区(buffer_to_write
)。如果你不喜欢的东西,而不是这样,你会好起来的:
/* A utility class that you can use */
class PacketWriter
{
private:
typedef std::vector<char> buffer_type;
static void WriteIsComplete(boost::shared_ptr<buffer_type> op_buffer, const boost::system::error_code& error, std::size_t bytes_transferred)
{
// Handle your write completion here
}
public:
template<class IO>
static bool WritePacket(const std::vector<char>& packet_data, IO& asio_object)
{
boost::shared_ptr<buffer_type> op_buffer(new buffer_type(packet_data));
if (!op_buffer)
{
return (false);
}
asio_object.async_write_some(boost::asio::buffer(*op_buffer), boost::bind(&PacketWriter::WriteIsComplete, op_buffer, boost::asio::placeholder::error, boost::asio::placeholder::bytes_transferred));
}
};
/* ... in thread 1 ... */
PacketWriter::WritePacket(packet_1, my_socket);
/* ... in thread 2 ... */
PacketWriter::WritePacket(packet_2, my_socket);
在这里,它会如果你通过你的线变成WritePacket以及帮助。你的想法,虽然。
答案#2:
我想你已经采取了非常不错的办法。一个建议,我会提供的是使用async_write
而不是async_write_some
,这样可以保证你的回调函数被调用之前,整个缓冲区被写入。
其他提示
抱歉,您有两个选择:
序列化写语句,无论是带有锁,还是更好地启动一个单独的作者线程,该线程从队列中读取请求,然后可以将其他线程堆叠在队列上,而无需太多争论(需要一些静音)。
给每个写入线程一个自己的套接字!如果电线另一端的程序可以支持它,那么这实际上是更好的解决方案。
您可以排队修改并在写处理程序中的数据执行它们。
网络将最可能在管的最慢的部分(假设你的修改都没有 computationaly贵),这样你就可以进行器官功能障碍综合征,而套接字层是送 以前的数据。
柜面你要处理大量的频繁连接/断开客户一起来看看 IO完成端口或类似机构。