升压插座问题

Issue with Boost Sockets

本文关键字:问题 插座      更新时间:2023-10-16

首先,我想声明我是C++和提升的初学者,尽管我确实有一些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例外。

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

你的字符串连接代码很残酷!

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();

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

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

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

长话短说,您的代码应该如下所示:

ostringstream oss;
oss << arg1 << "," << arg2 << "," << arg3 << "," << arg4 << "," << arg5 << "," << arg6;
string response = oss.str();
您使用

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

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

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

  • 使用boost::asio::阅读,就像你尝试的那样。
  • 使用这些函数的多次调用来读取越来越多的数据
  • 使用 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);