anti
anti

Reputation: 3125

boost::asio::ip::tcp::iostream, launch client first and wait for server?

I have an application that uses boost::asio::ip::tcp::iostream to connect to another application via tcp.

My server code is:

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

and my client is:

std::string ip = "127.0.0.1";

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

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

If the server is launched first, this works great. But if the client is launched first, it will throw the error and crash. What I would like to do is be able to launch either side first, and have it wait for the connection. The client is obviously the issue, so i am trying:

 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;
        }

    }

This will not compile, giving me an error on boost::asio::ip::tcp::iostream* stream, with Error C4703 potentially uninitialized local pointer variable 'stream' used. I have tried:

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

both compile, but crash. How can I have the client wait for the server, in this situation?

Upvotes: 1

Views: 812

Answers (1)

sehe
sehe

Reputation: 393447

Never use new¹. Because as you commented, if (!*stream) compiles but it leaks resource like there's no tomorrow.

In this case:

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

Which prints:

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

¹ unless you're writing a low-level resource wrapper for your library interface.

Upvotes: 4

Related Questions