"这" boost bind

时间:2016-07-27 12:49:54

标签: multithreading boost bind

我正在编写多线程服务器来处理来自许多tcp套接字的异步读取。这是困扰我的代码部分。

void data_recv (void) {
    socket.async_read_some (
            boost::asio::buffer(rawDataW, size_t(648*2)),
            boost::bind ( &RPC::on_data_recv, this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
} // RPC::data_recvW


void on_data_recv (boost::system::error_code ec, std::size_t bytesRx) {

     if ( rawDataW[bytesRx-1] == ENDMARKER {  // <-- this code is fine
         process_and_write_rawdata_to_file    
         }

     else {
        read_socket_until_endmarker            //  <-- HELP REQUIRED!!
        process_and_write_rawadata_to_file
        }
}

async_read_some几乎总是读取包括endmarker在内的数据,所以它工作正常。很少,终结者的到来会在流中延迟,而且当我的程序失败时。我认为它失败了,因为我还没有理解boost绑定是如何工作的。

我的第一个问题: 我对这个boost totorial example感到困惑,其中&#34;这个&#34;没有出现在处理程序声明中。 (请参阅示例中的start_accept()代码。)这是如何工作的?编译器会忽略&#34;这个&#34; ?

我的第二个问题: 在on_data_recv()方法中,如何从on_data()方法中读取的同一个套接字读取数据?换句话说,如何将socket作为参数从调用方法传递给处理程序?当处理程序在另一个线程中执行时?任何可以放入我的&#34; read_socket_until_endmarker&#34;将不胜感激。

1 个答案:

答案 0 :(得分:0)

  

我的第一个问题:我对这个提升的例子感到困惑,其中&#34;这个&#34;没有出现在处理程序声明中。 (请参阅示例中的start_accept()代码。)这是如何工作的?编译器会忽略&#34;这个&#34; ?

在示例中(我假设这也适用于您的函数)start_accept()是一个成员函数。 bind函数的设计非常方便,当您在其第一个参数前使用&时,它会将其解释为应用于其第二个参数的成员函数。

所以当这样的代码:

void foo(int x) { ... }
bind(foo, 3)();

相当于只调用foo(3)

这样的代码:

struct Bar { void foo(int x); }
Bar bar;
bind(&foo, &bar, 3)(); // <--- notice the & before foo

相当于调用bar.foo(3)

因此按照你的例子

boost::bind ( &RPC::on_data_recv, this, // <--- notice & again
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred)

在Asio中调用此对象时,它应相当于调用this->on_data_recv(error, size)。结帐this link了解详情。

对于第二部分,我不清楚你如何使用多个线程,你是否从多个线程运行io_service.run()(可能但我认为超出了你的经验水平)?可能是您将异步IO与多线程混淆的情况。我会假设是这样的,如果你纠正我,我会改变我的答案。

通常和preferred起点是只有一个线程运行io_service.run()函数。别担心,这将允许您异步处理许多套接字。

如果是这种情况,您的两个功能可以很容易地修改:

void data_recv (size_t startPos = 0) {
    socket.async_read_some (
            boost::asio::buffer(rawDataW, size_t(648*2)) + startPos,
            boost::bind ( &RPC::on_data_recv, this,
                    startPos,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
} // RPC::data_recvW


void on_data_recv (size_t startPos,
                   boost::system::error_code ec,
                   std::size_t bytesRx) {
     // TODO: Check ec

     if (rawDataW[startPos + bytesRx-1] == ENDMARKER) {
         process_and_write_rawdata_to_file    
     }
     else {
        // TODO: Error if startPos + bytesRx == 648*2
        data_recv(startPos + bytesRx);
     }
}

注意上面的代码仍有问题,主要的一个是如果另一方一个接一个地快速发送两条消息,我们可以接收(在一个async_read_some调用中)完整的第一条消息+第二条消息的一部分,从而错过了第一个ENDMARKER。因此,仅测试最后接收的字节是否= = ENDGARKER是不够的。

我可以继续进一步修改这个功能(我想你可能会对这个功能有所了解),但你最好还是使用async_read_until,这正是出于此目的。