Network test behaving strangely?


#1

I’m trying to build a simple JUCE app (Audio Application) that tries to connect to itself on another computer over the network and sends a hello-world type message upon connection. I thought I was all finished, but it’s not behaving the way I expected and I can’t figure out why. Here is my code:

    server->beginWaitingForSocket (PORT, ""); // empty string means listen on all host IPs
    // try to connect to all possible IPv4 addresses
    Array<IPAddress> interfaceIPs;
    IPAddress::findAllAddresses (interfaceIPs);
    for (auto ip : interfaceIPs) {
        //if (ip.address[0] == 127) continue; // skip localhost
        for (uint8 i = 1; i <= 255; ++i) {
            IPAddress test (ip.address[0], ip.address[1], ip.address[2], i);
            if (ip == test) continue; // avoid trying to connect to ourself
            if (client->isConnected()
            || client->connectToSocket (test.toString(), PORT, TIMEOUT)) {
                // found a connection, so stop looking for more
                std::cout << "Connected to " << test.toString() << std::endl;
                server->stop();
                break;
            }
        }
    }

What this code is supposed to do is: start a server listening for connections, and meanwhile try to connect to every possible IP address in the network with the given port. I’m trying to achieve a P2P setup where either computer can be host or client.

The variables client and server are instances of InterprocessConnection and InterprocessConnectionServer, respectively. PORT and TIMEOUT are macros defined elsewhere. They’re currently set to 9001 and 100, but I’d appreciate feedback on those choices. Especially TIMEOUT, because I have no idea how long a connection attempt’s timeout should be and just guessed at 100ms.

If I run that as-is, I immediately get the basic black screen, displaying a message I set that should only show up when InterprocessConnection::disconnect() is called. The terminal output I get is:
JUCE v4.3.1
Connected to 127.0.0.2
Connected to 192.168.1.1
Connected to 10.42.1.2
Connected to 10.42.0.2

That makes no sense, because it’s supposed to break the loop on its first connection, not its first 4. Is there some asynchronous multi-threaded stuff going on that I don’t know about? (EDIT: Nevermind, I just realized it’s doing that because I’m not breaking out of the outer loop.) And why is it successfully establishing connections with nonexistent devices in my network? 127.0.0.1 is localhost for me, not .2, 192.168.1.1 is actually NOT my router (it’s .254), 10.42.1.X is an ethernet cable going to the other computer (host is 10.42.1.1 while the other is currently 10.42.1.83), and 10.42.0.X is an ethernet cable going to a device that’s TURNED OFF. All 4 of those IP addresses don’t go anywhere at all. But at least it is successfully skipping the addresses that refer to this device itself.

You may have noticed the line that leaves out localhost is commented right now. That’s because of the other issue that I can’t figure out. When it’s uncommented–in fact, when I attempt to skip localhost in any way at all (originally I was doing it further inside the loop with IPAddress::localhost())–the program hangs forever before finishing initializing (i.e. I just get a tiny window that nothing’s drawing onto, no terminal output past JUCE v4.3.1, and no response to SIGINT; only SIGTERM stops it).

EDIT: OK, figuring out that outer loop issue has actually shedded a lot of light on this issue. It seems that the single problem I’m having is, InterprocessConnection::connectToSocket() is returning true despite “connecting” to an IP address that isn’t active at all, and when I try to do stuff with that address, problems ensue.


#2

This is a very strange way of achieving what you want. What you really want to do is to broadcast something to all other hosts on the network - google for tcp/ip broadcast. For IPv4 broadcasting a ‘find’ request for your service and responding to it from your host would be a typical pattern, for IPv6, it’s basically multicast, which would also be a fine pattern for IPv4.

Your code looks quite mangled though, with assumptions about address classes etc. I’d run ifconfig or equivalent on your host and look at the interfaces you have defined - it’s quite possible to have a few. My box here for example has 5.


#3

OK, cool, I didn’t know about broadcast/multicast. I’m not sure what assumptions about address classes you think I’m making, though. Reading the OP should have made it clear that I am somebody who knows about all their interfaces and uses ifconfig (or ip addr/link/etc.) often. I’ll try having it work that way instead, but I still don’t understand why InterprocessConnection::connectToSocket() is immediately returning true for any IP address I give it, including ones that don’t go anywhere.