10
\$\begingroup\$

I built a library for purely cross-platform programming. My games made with it run fine in Android , Pc, Linux, Mac etc.

The networking capabilities are provided by ENET library, therefore all communication between my apps is not TCP or UDP compatible, but only in the custom protocol, even tough its based on the UDP ultimately.

I don't think its possible to do what i want with ENET, thats why I ask here for help!

Lets say I have the same game running in my Android phone, my laptop and my pc. They are all in the same wifi network, and therefore in a LAN, whether its Wifi hotspot(?) or the household router.

I need each of those 3 peers to discover the other two in the network. This is meant only to find the IP of alive apps in the LAN network, to be able to host multiplayer games between them.

I can only think of one effective way to do this, UDP broadcast, wait responses, but if that is the solution, i need something small, since its the only purpose of the implementation.

Other way could be to try to connect to all IPs in the LAN address subrange, but I don't think the OS would be with me on this one :p

\$\endgroup\$
3
  • 2
    \$\begingroup\$ I think a few UDP broadcasts are the way to go, and I don't understand your objections to it, or is it that ENET doesn't support broadcasts? \$\endgroup\$
    – Roy T.
    Commented Jun 18, 2012 at 7:42
  • \$\begingroup\$ Exactly, it doesn't, it can only broadcast to already known peers.. \$\endgroup\$
    – Grimshaw
    Commented Jun 18, 2012 at 11:25
  • \$\begingroup\$ stackoverflow.com/questions/683624/… Does this influence an answer? \$\endgroup\$
    – Grimshaw
    Commented Jun 18, 2012 at 14:30

3 Answers 3

7
\$\begingroup\$

As many people have been saying, the solution would be to use UDP broadcast, but there's a lot of implementation details involved. I recently ran into the same problem, and after working out a solution I've made a blog post, and a sample project in the form of a LAN chat server/client. I'll be summarising those here, but you should check them out for more details, and real code.

Here's how it works, based on a description by Lee Salzman, creator of ENet:

  • Your game server runs on one socket, as an ENet host
  • The server also binds to a known "listen" port, as a regular UDP socket (i.e. not an ENet host)
  • The client sends a UDP broadcast message (i.e. IP 255.255.255.255) to that listen port, and waits for responses
  • All servers in the LAN will receive that "scanning" message, and respond. Ideally you can respond with the port that the game server (ENet host) is running on; that way you don't have to have your game server running on a fixed port)
  • After the client has received some responses, it will know which servers are present. Then you can choose one of them to connect to, as a regular ENet peer. At this point the client doesn't need the UDP "scanner" socket anymore.

The good news is that ENet provides wrapper functions for using sockets, so you can do everything in ENet. The bad news is that the wrapper is extremely thin; you'll need to know about socket programming, such as what select() does. This is why I encourage you to take a look at the blog post and sample project so you can copy/paste the code and save yourself lots of time.

Here are some notes and pitfalls should you choose to do your own implementation:

  • The listener/scanner must be UDP, so you need to create them using enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM) (or SOCK_DGRAM for plain old socket programming)
  • For the server "listener", allow the port address to be reused using enet_socket_set_option(socket, ENET_SOCKOPT_REUSEADDR, 1) (or SO_REUSEADDR) so that multiple servers can run on the same IP
  • For the client "scanner", you must enable broadcasts on the UDP socket using enet_socket_set_option(scanner, ENET_SOCKOPT_BROADCAST, 1) (or SO_BROADCAST), otherwise you can't send to the broadcast address. This is a safety feature only, to make it harder to accidentally flood the network.

Unfortunately this isn't exactly a "lightweight" solution; the sample project clocks in at a few hundred LOC altogether. It would be nice if this were packaged into a utility library for ENet, but I've found that for game servers, you often want to send some more game-specific information with the server reply to make this useful, such as:

  • The game type (e.g. "co-op", "deathmatch")
  • The "map", "level" or "campaign" the server is running
  • The number of players and max players for the server
  • Any other game-specific information that will affect the client's decision to connect or not. Think about the "server browsers" in games and the sort of information they show.
\$\endgroup\$
1
  • \$\begingroup\$ This is exactly what I was thinking. Broadcasting is the way to go. \$\endgroup\$
    – Lucien
    Commented Mar 1, 2016 at 6:06
2
\$\begingroup\$

When you don't want to leave your library, you could just use brute-force and attempt to connect to each one of the possible addresses. Most home lans are Class-C networks (/24) where the first 24 bit of the IP address are the same and the last 8 bit differ. So you only have 255 possible IP addresses.

But still, doing an UDP broadcast would be the cleaner alternative. Just send an UDP packet to 255.255.255.255 and all clients behind the same router will receive it. They can then send a reply to the source IP and source port of the packet to inform the sender that they are present.

\$\endgroup\$
3
  • 3
    \$\begingroup\$ Please please please please please don't brute-force. \$\endgroup\$ Commented Jan 15, 2013 at 0:25
  • \$\begingroup\$ @TrevorPowell ...because...? \$\endgroup\$
    – Philipp
    Commented Jan 15, 2013 at 8:21
  • 3
    \$\begingroup\$ Because it's the wrong solution. It won't work in universities (which do not use class-c networks) or at businesses (which also typically do not use class-c networks), and the IT staff at either will intensely dislike the load caused by having every player make brute-force attempts to send messages to every IP address in their network every time they click a 'refresh' button. It's just a bad solution to the problem. This question of locating potential peers without a mathmaking server is precisely what broadcast is for. Use broadcast. It's better in every way. :) \$\endgroup\$ Commented Jan 15, 2013 at 9:04
1
\$\begingroup\$

You could have a look at DNS-SD/ZeroConf/Avahi/Bonjour/mDNS. It's the stuff Apple use to share printers, iTunes folders and so on but it's been adopted elsewhere. Avahi is the opensource version that Linux uses (not sure if it's Linux only), not sure how portable the whole thing is (although there are implementations for most platforms).

Having said all that, it's probably easier to just do the UDP broadcast.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .