boost::asio::ip::tcp::iostream,首先启动客户端并等待服务器?

Posted

技术标签:

【中文标题】boost::asio::ip::tcp::iostream,首先启动客户端并等待服务器?【英文标题】:boost::asio::ip::tcp::iostream, launch client first and wait for server? 【发布时间】:2018-03-03 10:39:33 【问题描述】:

我有一个应用程序使用 boost::asio::ip::tcp::iostream 通过 tcp 连接到另一个应用程序。

我的服务器代码是:

static auto const flags = boost::archive::no_header | boost::archive::no_tracking;
boost::asio::io_service ios;
boost::asio::ip::tcp::endpoint endpoint
= boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 4444);
boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
boost::asio::ip::tcp::iostream stream;

//program stops here until client connects.
acceptor.accept(*stream.rdbuf());

我的客户是:

std::string ip = "127.0.0.1";

    boost::asio::ip::tcp::iostream stream(ip, "4444");

    if (!stream)
        throw std::runtime_error("can't connect");

如果服务器首先启动,这很好用。但是如果先启动客户端,就会抛出错误并崩溃。我想做的是能够先启动任一侧,并让它等待连接。客户显然是问题所在,所以我正在尝试:

 bool bConnected;

    std::string ip = "127.0.0.1";
    boost::asio::ip::tcp::iostream* stream;

    while (!bConnected)
    
        stream = new boost::asio::ip::tcp::iostream(ip, "4444");
        if (!stream)
        
            std::cout << "cannot find datastream" << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(50));
            //throw std::runtime_error("can't connect");
        

        if (stream)
        
            bConnected = true;
        

    

这不会编译,在boost::asio::ip::tcp::iostream* stream 上给我一个错误,Error C4703 potentially uninitialized local pointer variable 'stream' used。我试过了:

boost::asio::ip::tcp::iostream* stream = nullptr; boost::asio::ip::tcp::iostream* stream = NULL;

都编译,但崩溃。在这种情况下,如何让客户端等待服务器?

【问题讨论】:

我怀疑您收到的是错误,而是警告。不过,这不可能说,因为您没有向我们展示我们真正需要的构建的实际输出(完整和完整)。 做什么使用未初始化的并且很可能是警告(和崩溃)的原因是变量bConnected。未初始化的局部变量的值是indeterminate(并且看起来是随机的)并且在没有初始化的情况下以任何方式使用它们是未定义的行为 更新了停止编译的实际警告。 Error C4703 potentially uninitialized local pointer variable 'stream' used @Someprogrammerdude 说了什么。试试bool bConnected = false;(和stream=nullptr 是很好的衡量标准)。原因:如果 bConnected 恰好为真,则跳过整个 while 块而流是,下面的代码将访问未初始化的流 现在你有另一个问题,那就是检查stream变量的条件。它是一个指针,所以if (!stream) 不会检查连接是否成功,而是检查 pointer 是否为空指针。条件!stream 等于stream == nullptr(并且条件中的普通stream 等于stream != nullptr)。要解决这个问题,请考虑如何获取指针指向的对象。 【参考方案1】:

切勿使用new¹。因为正如您评论的那样,if (!*stream) 编译但它会泄漏资源,就像没有明天一样。

在这种情况下:

Live On Coliru

#include <boost/asio.hpp>
#include <iostream>
#include <thread>

using boost::asio::ip::tcp;

int main() 
    tcp::iostream stream;

    do 
        std::cout << "Connecting...\n";

        stream.clear();
        stream.connect("127.0.0.1", "4444");

        std::this_thread::sleep_for(std::chrono::milliseconds(500));
     while (!stream);

    std::cout << "Connected! " << stream.rdbuf();

哪些打印:

Connecting...
Connecting...
Connecting...
Connecting...
Connecting...
Connecting...
Connected! Hello world

¹除非您正在为库接口编写低级资源包装器。

【讨论】:

我喜欢你在 Coliru 上使用 netcat :) 不知道它是否可用 @djf 它仅限于环回

以上是关于boost::asio::ip::tcp::iostream,首先启动客户端并等待服务器?的主要内容,如果未能解决你的问题,请参考以下文章