无条件地使用代码0来提升asio退出。在有问题的语句解决它之后设置断点

时间:2014-07-13 14:08:13

标签: c++ boost boost-asio

我正在使用boost asio编写TCP服务器 - 客户端对。它非常简单和同步。

服务器应该通过对通过TCP传输数据包的函数的几次递归调用来传输大量二进制数据。客户端通过递归函数执行模拟,读取和附加数据,该函数从套接字读取传入的数据包。

然而,在接收此数据的过程中,大多数时候(大约80%)客户端突然停止递归,总是在其中一个读取调用之前(如下所示)。鉴于在递归之后还有其他一些语句和函数调用,它不应该能够这样做。

size_t bytes_transferred = m_socket.read_some(boost::asio::buffer(m_fileReadBuffer, m_fileReadBuffer.size()));

m_fileReadBuffer是一个char :: boost数组,大小为4096(虽然我已尝试过其他缓冲格式但没有成功)。

绝对没有办法想象推断为什么会发生这种情况。

  • 程序立即退出,因此我无法将错误代码传递给read_some并读取任何错误消息,因为这需要在read_some语句之后发生
  • 不会抛出异常
  • 编译/运行时没有错误或警告
  • 如果我在递归函数中放置断点,问题永远不会发生(传输成功完成)
  • 如果我在转移后放置断点,或者在转移后陷阱执行陷阱,则问题永远不会发生,并且没有任何错误迹象

另外,请注意服务器始终成功发送所有数据,这一点非常重要。最重要的是,问题总是发生在传输的最后:我可以发送8000个字节,当传输大约6000或7000个字节时它会退出,我可以发送8000000个字节,它会在7996000字节之后退出已被转移。

我可以提供任何必要的代码,我只是不知道问题出在哪里。下面是客户端上的递归读取函数:

void TCP_Client::receive_volScan_message()
{
    try
    {
        //If the transfer is complete, exit this loop
        if(m_rollingSum >= (std::streamsize)m_fileSize)
        {
            std::cout << "File transfer complete!\n";
            std::cout << m_fileSize << " "<< m_fileData.size() << "\n\n";               

            return;
        }

        boost::system::error_code error;        

        //Transfer isn't complete, so we read some more        
        size_t bytes_transferred = m_socket.read_some(boost::asio::buffer(m_fileReadBuffer, m_fileReadBuffer.size()));

        std::cout << "Received " << (std::streamsize)bytes_transferred << " bytes\n"; 

        //Copy the bytes_transferred to m_fileData vector. Only copies up to m_fileSize bytes into m_fileData
        if(bytes_transferred+m_rollingSum > m_fileSize) 
        {
            //memcpy(&m_fileData[m_rollingSum], &m_fileReadBuffer, m_fileSize-m_rollingSum);
            m_rollingSum += m_fileSize-m_rollingSum;
        }
        else
        {
           // memcpy(&m_fileData[m_rollingSum], &m_fileReadBuffer, bytes_transferred);
            m_rollingSum += (std::streamsize)bytes_transferred;  
        }                     

        std::cout << "rolling sum: " << m_rollingSum << std::endl;

        this->receive_volScan_message();
    }
    catch(...)
    {
        std::cout << "whoops";
    }                
}

作为建议,我尝试在客户端和服务器上将递归循环更改为for循环。不知何故,这个问题仍然存在。唯一的区别是现在不是在前面提到的read_some调用之前退出0,而是在其中一个for循环块的末尾退出0,就在它开始执行另一个for循环传递之前。

编辑:事实证明,每当我在IDE上以调试模式构建客户端时,都不会发生错误。

1 个答案:

答案 0 :(得分:0)

我还没有完全理解这个问题,但是我已经完全解决了这个问题。

问题的根源在于,在客户端上,如果服务器消息尚未到达,则boost::asio::read调用进行主要退出,代码为0。这意味着一个简单的

while(m_socket.available() == 0)
{
    ;
}  

在所有读取调用完全阻止问题之前。两者都处于调试和发布模式。

这很奇怪,因为我理解这些函数应该阻塞直到有东西要读,即使它们遇到错误也应该返回零。

我认为调试/发布差异的发生是因为m_readBuffer在读取调用发生时没有初始化为任何内容。这使得read调用返回某种形式的无声错误。在调试时,未初始化的变量会自动设置为NULL,从而悄悄解决我的问题。

我不知道为什么在传输之后添加while循环会阻止此问题。在m_readBuffer设置并成功使用多次之后,传输的 end 通常都发生了原因。

最重要的是,我从未见过这种类型的&#34;崩溃&#34;之前,程序只是在随机位置使用代码0退出,没有抛出任何错误或异常。