1

首先,我想声明我是 C++ 的初学者,并且总体上是 boost,尽管我确实有一些使用 Java 和 C# 等语言的经验。

话虽如此,我在通过 Boost TCP 套接字传输数据时遇到了问题。我正在使用这段代码:

发送:

tcp::socket s(io_service);
        boost::asio::connect(s, iterator);
        string response = static_cast<ostringstream*>( &(ostringstream() << arg1) )->str() 
            + "," + static_cast<ostringstream*>( &(ostringstream() << arg2) )->str()
            + "," + static_cast<ostringstream*>( &(ostringstream() << arg3) )->str()
            + "," + static_cast<ostringstream*>( &(ostringstream() << arg4) )->str()
            + "," + static_cast<ostringstream*>( &(ostringstream() << arg5) )->str()
            + "," + static_cast<ostringstream*>( &(ostringstream() << arg6) )->str();

        //pad the rest
        while (response.length() < max_length)
        {
            response += ' ';
        }
        boost::asio::write(s, boost::asio::buffer(response, sizeof(response))); 

读书:

tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
    while(true)
    {
        socket_ptr sock(new tcp::socket(io_service));
        a.accept(*sock);
        boost::thread t(boost::bind(session, sock));
    }
...
void session(socket_ptr sock)
{
    char data[max_length];
    size_t length;
    try
    {
        while(true)
        {           
            boost::system::error_code error;
            //size_t length = sock->read_some(boost::asio::buffer(data), error);
            length = boost::asio::read(*sock, boost::asio::buffer(data, sizeof data));
            std::cout << "Length " << length << endl;
            if (error == boost::asio::error::eof)
            {
                break; // Connection closed cleanly by peer.
            }
            else if (error)
            {
                throw boost::system::system_error(error); // Some other error.
            }

        }
    }
    catch (std::exception& e)
    {
        std::cout << data << endl;  
        string message = e.what();
        if(std::string::npos != message.find(END_OF_FILE))
        {
            domeSomethingWithTheData(data); 
            memset(data, 0, sizeof data);
        }
        else
        {
            std::cout << data <<endl;
            std::cerr << "Exception in thread: " << e.what() << "\n";
        }
    }
}

我无法理解的是,无论我使用什么(boost::asio::readsock->read_some),我都不会得到超过 32 个字符的数据。我尝试将缓冲区的大小增加到2048,但问题仍然存在。

缓冲区总是包含超过 32 个字符(其中大部分是垃圾),但我假设这些字符实际上并不是从客户端发送的,而是来自服务器端缓冲区的实际分配,因为std::cout << "Length " << length打印出 32。

任何有关我如何从客户端向服务器发送任意数量的字符的信息都将不胜感激。

编辑:

在 Rafal Rawicki 提供的指针之后,我现在正在使用以下代码:

 boost::asio::streambuf buffer;
    boost::asio::read_until(*sock, buffer, '\n');
    std::istream is(&buffer);
    std::string line;
    std::getline(is, line); 
    std::cout << line << std::endl;

客户端保持不变,唯一的例外是我\n在最后添加了一个。然而,这会产生很多End of file异常。

4

2 回答 2

3

这实际上不是您问题的答案。但是一个简短的建议。

你的字符串连接代码太残忍了!

string response = static_cast<ostringstream*>( &(ostringstream() << arg1) )->str() 
        + "," + static_cast<ostringstream*>( &(ostringstream() << arg2) )->str()
        + "," + static_cast<ostringstream*>( &(ostringstream() << arg3) )->str()
        + "," + static_cast<ostringstream*>( &(ostringstream() << arg4) )->str()
        + "," + static_cast<ostringstream*>( &(ostringstream() << arg5) )->str()
        + "," + static_cast<ostringstream*>( &(ostringstream() << arg6) )->str();

对于每个 arg 你创建一个 new ostringstream,将值写入它,然后你不必要地取消引用它,然后你不必要地将它转换为它已经拥有的类型。最后,您使用字符串连接来构建最终字符串。

这种字符串连接既不高效,也不复杂(需要临时对象、一些浪费的分配等等)。

ostringstream是字符串连接和格式化的正确工具,它高效且复杂。

长话短说,你的代码应该是这样的:

ostringstream oss;
oss << arg1 << "," << arg2 << "," << arg3 << "," << arg4 << "," << arg5 << "," << arg6;
string response = oss.str();
于 2012-05-23T20:56:34.660 回答
2

boost::asio::read您使用应该读取数据,直到缓冲区已满或发生错误。

boost::asio::socket::read_some应该从套接字读取一些数据。

要读取所需的数据量,您可以:

  • 尝试使用 boost::asio::read 。
  • 使用这些函数的多次调用来读取越来越多的数据
  • 用于read_until将数据读取到预期的分隔符
  • 使用这个boost::asio::read重载,它接受一个参数completion_condition,例如字节数。

此外,请查看Boost.Asio的同步操作问题,并考虑改用异步操作。

编辑:我错过了客户端代码中不正确的缓冲区初始化。的使用boost::asio::read是正确的。

你不能像这样初始化缓冲区:

boost::asio::buffer(response, sizeof(response));

因为sizeof返回std::string结构的大小,而不是整个字符串。在我的机器上它总是 8。使用:

boost::asio::buffer(response);
于 2012-05-23T19:12:55.003 回答