Server browser - Persist connections or get server data via some other means?

What is the best way to get the status of a server to load into a server browser?

Imagine that I have hundreds of servers and thousands of clients

Should I:

  1. get each client to open a new connecion to each server then persist this connection for every refresh and then only close the connections when I choose a server to join (keeping just this one open)
  2. get each client to open a new connecion to each server then close it after getting the status, then open the connection again every refresh and when I choose a server to join?
  3. get the server status by some other means, HTTP for example?

Most efficient way would be to have the server publish its status to a central list that the clients just pull as a web page or something. Connecting to hundreds of servers is going to be pretty time consuming no matter what… better not to poll.

1 Like

Ok thanks for the input.

However having a central location to publish all servers’ statuses is not achievable currently and even doing so would lose valuable information for me ie. ping.

I think that what I will do is to have persistent connections (recreating them is too costly I think). Then discard the not needed ones when I choose a certain server to join.

But I think that I may have to build in some mechanism into the server to drop connections if it becomes too loaded which would mean that the client would need to check that it is still connected before sending a new request, or at least catch an exception and then re-open the connection and retry the message.

Connecting to 100 servers from each client is pretty crazy… I doubt you are showing all of those servers on a screen at the same time anyway. There is no way any game on earth does it this way.

Generally, the servers will implement some low resource connection (say an open UDP port or something) and just respond to pings on that port… and then clients will only ping rarely and only what is displayed. (Hint: don’t use SpiderMonkey for that as it’s not even a real connection.)

Initiating full connections for every server you want to ping is going to be pretty bad… for both the clients and the servers.

The way battlefield does this is by using a centralized server to retain and sort data, while each server uses a specific “query” port that returns regular json.

You query the primary server:

var data = { 
    type: "co-op",
    max-players: "32",
    min-players: "5" ,
    order: "max-players"
}

…and the primary server will give you a lazy list of servers that match your requirements:

[
    {
        name: "my awesome server",
        players: "19",
        max-players: "32",
        ping: "54ms",
        location: "France",
        level: "somelevelnamethatmeanssomething."
    },
    {
        name: "someotherserver.",
        players: "11",
        max-players: "32",
        ping: "43ms",
        location: "Italy",
        level: "somelevelnamethatmeanssomething."
    }
]

This way you maintain a lot of control, can cache results by the second…

Yeah, sort of like my first suggestion… somehow the client has to find out about the 100 servers anyway so there must be some central list.

Forgive me for being naive then but how is one able to cache ping? Surely this is specific to each client.

This is all good food for thought though. Really in my application I will only have a few servers (that a user would manage) and each user would only contact the servers in their list (similar to Minecraft). But I was wondering how scalable this was so that I could have a one-size-fits-all approach but it seems that this is not realistically achievable.

You would get the IP too so that you can actually join to it, which you can also use to ping for a local ping speed. Ping speeds are primarily determined on location (and thus route of said location) - so again - as battlefield does it - sort by country and then ping.

Regarding caching ping - it has a lot to be said for it.

  • The server is up. It is responding and active.
  • Pinging the query port gives you reasonable confirmation the server is running your game, and that you can/should proceed trying to actually query the port.
  • It has an acceptable ping rate as far as pings go, so is deemed worthy of joining.
  • It has an abnormally high ping speed and should be truncated from results, possibly put into a seperate list and query that list every minute or two to determine when it returns to an acceptable state.

But Java does not support ICMP so don’t I have to open a new socket to ping to and am I then not back to my original problem?

It’s not a problem until you build a connection for each query. That why you shouldn’t use TCP or connections over UDP (spidermonkey). What you need is a simple UDP server that replies to each query with a packet providing all data you need and by measuring the time between the query and the response you get the ping.

Yes, exactly.

Would I be able to achieve this using the DatagramSocket and DatagramPacket classes in your opinion?

Datagram packets are used to implement a connectionless packet
delivery service

Sounds like what you guys are suggesting.

Yes, that’s what we are suggesting.