read_some()工作但非常慢,read()没有

时间:2014-12-03 09:03:52

标签: c++ boost boost-asio

下面的代码绝对有效,但并不像我预期的那样快。

我希望我的程序以非常好的速度读取数据。还有另一个商业应用程序连接到同一服务器和以惊人的速度检索数据。服务器端不是问题。

class A
{
    //...

    boost::asio::ip::tcp::socket* myPort;
}

void A::OpenPort()
{
    if(myPort)
    {
        if(myPort->is_open())
        {
            return;
        }
    }

    // make the connection
    Connect();

    if(! myPort->is_open())
    {
        return;
    }

    // set the protocol
    static string init("INIT\r\n");
    myPort->write_some(boost::asio::buffer(init.c_str(), init.length()));
}   

void A::Read()
{
    static string prev_msg = "";

    try
    {
        OpenPort();

        while(true)
        {                   
            boost::system::error_code error;

                boost::asio::streambuf streamBuf;
                boost::asio::streambuf::mutable_buffers_type mutableBuffer = streamBuf.prepare(614400);
                size_t bytes_transferred = myPort->read_some(boost::asio::buffer(mutableBuffer), error);

                if (error)
                {
                    if (error != boost::asio::error::eof)
                    {
                        throw boost::system::system_error(error); // Some other error.
                    }
                }

                // add to any previous message we might not have processed
                streamBuf.commit(bytes_transferred);
                istreambuf_iterator<char> sbit(&streamBuf);
                istreambuf_iterator<char> end;
                string s(sbit, end);
                prev_msg.append(s);

                string delimiter1 = ",\r\n";

                size_t pos1 = 0;

                string response;

                while ((pos1 = prev_msg.find(delimiter1)) != std::string::npos)
                {
                    response = prev_msg.substr(0, pos1);

                    //SOME PROCESSING ON THE RESPONSE RECEIVED
                }
        }
    }
    catch (boost::system::system_error const& ex)
    {
        cout<<ex.what();
    }
}
显然,问题是read_some(),程序在一次读操作中不读取完整数据,有时它接收614000字节,有时甚至更少。 我不想强制对缓冲区大小施加任何限制,无论服务器发送什么,程序都应该一次性读取所有数据。

因此,我决定只使用read()。但是,现在程序停留在read(); read()调用不会返回。

boost::asio::streambuf streamBuf;
size_t bytes_transferred = read(*myPort, streamBuf, error);

if (error)
{
    if (error != boost::asio::error::eof)
    {
        throw boost::system::system_error(error); // Some other error.
    }
}

我必须在请求下一个数据之前处理收到的数据,因此我不能使用async_read()。

2 个答案:

答案 0 :(得分:1)

一些事情:

  • 使用TCP,您永远不能确定您将一次性收到所有内容。
  • 因为您正在读取分隔符,read_until()可能就是您所追求的目标。
  • 确保使用O_NDELAY打开套接字,否则将为写入添加200毫秒。通过在代码中的适当位置调用myPort->set_option(tcp::no_delay(true))来执行此操作。
  • 睡觉不是个好主意。设计您的代码,使其不必要。
  • 如果套接字关闭,您的代码似乎会进入无限循环。
  • 您无需检查返回值即可调用write_some()。您应该致电write()以确保所有数据都已写入。
  • 如果您有许多线程,您可能会从重新设计代码变为异步中获得改进。

答案 1 :(得分:1)

不要在每个循环上分配新缓冲区,只在循环外执行一次。

    while(true)
    {                   
        boost::system::error_code error;

            boost::asio::streambuf streamBuf;
            boost::asio::streambuf::mutable_buffers_type mutableBuffer = streamBuf.prepare(614400);
            size_t bytes_transferred = myPort->read_some(boost::asio::buffer(mutableBuffer), error);
...

替换为

    boost::system::error_code error;
    boost::asio::streambuf streamBuf;
    boost::asio::streambuf::mutable_buffers_type mutableBuffer = streamBuf.prepare(614400);
    while(true)
    {                   
            size_t bytes_transferred = myPort->read_some(boost::asio::buffer(mutableBuffer), error);
...