我正在使用 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,这样可以保证你的回调函数被调用之前,整个缓冲区被写入。

其他提示

抱歉,您有两个选择:

  1. 序列化写语句,无论是带有锁,还是更好地启动一个单独的作者线程,该线程从队列中读取请求,然后可以将其他线程堆叠在队列上,而无需太多争论(需要一些静音)。

  2. 给每个写入线程一个自己的套接字!如果电线另一端的程序可以支持它,那么这实际上是更好的解决方案。

您可以排队修改并在写处理程序中的数据执行它们。

网络将最可能在管的最慢的部分(假设你的修改都没有 computationaly贵),这样你就可以进行器官功能障碍综合征,而套接字层是送 以前的数据。

柜面你要处理大量的频繁连接/断开客户一起来看看 IO完成端口或类似机构。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top