Is there a way to shortcut SpiderMonkey?

You can easily pick an available port just by temporarily opening your own ServerSocket on an ethereal port and seeing what port you are bound to.



Still, part of me thinks that a design that doesn’t support swapping out the network bits for local versions is kind of hacky… but it is simpler, I guess.

what pspeed said, just use a free port and you are fine.

@zarch

My current design has a clear distinction between client and server.

Server runs the world simulation and is always headless.

Client does user interaction and talks to the server to send game commands and query the world state.



Funnily enough, my initial design had a “console mode” for the server where it would display server stats and offer anything I might later add for diagnostics. Then I quickly discovered that this design would be too inflexible: no way to run a remote console, no way to run multiple consoles at the same time.

At that point, I decided that it’s far better to build the console as a special kind of client.

Maybe that’s a general design principle: “Always make the server headless.” It will be interesting to see whether this is really true, or true with exceptions, or just bogus. (Well, I have an exception already: if there’s no server because the game doesn’t provide for any kind of networking.)

@pspeed

I had to dig a bit around to uncover the following information, but here it is:



Port numbers in the 0…49151 range should not be used except after registration with the IANA, leaving the 49152…65535 range for random port number picking.



Source: Service Name and Transport Protocol Port Number Registry

(Use wget or some other non-browser to download this and view it in a text editor. The XML is invalid and not displayed as intended in a browser.)

“Assigned ports both System and User ports SHOULD NOT be used without or prior to IANA registration.”



I think I’ll use a random port number instead of cutting out SM.

Is there any interest in integrating that into SM? I could provide patches.

Screw that IANA stuff, nobody cares about that anyway. (add list of nearly all games known in mind)

Just dont use 0-1024 since on linux you can get problems without administrator rights.

(Also keep in mind that at any time some random source in the internet can send you crap at your application, so make sure it stays stable in this event (like a game client with a outdated serverlist trying to connect to a ip you currently use)

That most games don’t follow RFC 6335 isn’t suprising given that it’s from August 2011.

It’s still a good idea to follow it:

(a) starting at 49152 isn’t harder than starting at 1025;

(b) while port conflicts are just a paper cut, it’s the multitude of papercuts that makes server administration unnecessarily painful.



Here’s my class, for general ridicule:

[java]import java.util.Random;



public class RandomPort {



/**

  • Minimum port number that {@link #get()} may return.

    */

    public static int MIN = 49152;



    /**
  • Maximum port number that {@link #get()} may return.

    */

    public static int MAX = 65535;



    /**
  • @return A random dynamic port number as specified by RFC 6335.

    */

    public static int get() {

    // Usually, seeding a random number generator from the millisecond

    // clock is considered a bad idea since two such PRNGs tend to be

    // tightly correlated.

    // However, we don’t care about correlation between port number and

    // game content, so it’s marginally okay in this case. I hope.

    Random random = new Random(System.currentTimeMillis());

    return random.nextInt(MAX + 1 - MIN) + MIN;

    }



    }[/java]

Yes. The reserved ports used to run from 0 to 1024. I didn’t actually know they had extended that range and it seems a bit odd considering all existing software will not comply. Maybe it’s an IPv6 thing?

I’m sure it’s unrelated to IPv6.



Until August 2011, all port numbers were governed by IANA port numbering policy. That policy was often ignored, but those who cared about port conflicts (or got bitten by one) applied for a port number and usually got one.



RFC 6335 is new in that it reserves a port range to “will never be allocated, do as you wish but don’t assume any port free”. It’s intended for services where the port number isn’t assigned statically but kept in some registry.

Why 49152 as minimum port number? I can only guess, but I assume that some relatively important service already had 49151 already assigned to and they didn’t want to revoke that assignment (until Aug 2011, there never has been a policy for revoking a port assignment).



This all was news to me, too :slight_smile:

@toolforger said:
That most games don't follow RFC 6335 isn't suprising given that it's from August 2011.
It's still a good idea to follow it:
(a) starting at 49152 isn't harder than starting at 1025;
(b) while port conflicts are just a paper cut, it's the multitude of papercuts that makes server administration unnecessarily painful.

Here's my class, for general ridicule:
[java]import java.util.Random;

public class RandomPort {

/**
* Minimum port number that {@link #get()} may return.
*/
public static int MIN = 49152;

/**
* Maximum port number that {@link #get()} may return.
*/
public static int MAX = 65535;

/**
* @return A random dynamic port number as specified by RFC 6335.
*/
public static int get() {
// Usually, seeding a random number generator from the millisecond
// clock is considered a bad idea since two such PRNGs tend to be
// tightly correlated.
// However, we don't care about correlation between port number and
// game content, so it's marginally okay in this case. I hope.
Random random = new Random(System.currentTimeMillis());
return random.nextInt(MAX + 1 - MIN) + MIN;
}

}[/java]


You don't need to do this. You'd have to do it again and again in case of port conflict. It's WAY easier to let the networking layer find an open port for you by opening a server socket without a port. It will pick one from the ethereal ports (the high ones that you mention).

Edit: just open a ServerSocket, grab the port it's bound to and then close it again.
@toolforger said:
I'm sure it's unrelated to IPv6.

Until August 2011, all port numbers were governed by IANA port numbering policy. That policy was often ignored, but those who cared about port conflicts (or got bitten by one) applied for a port number and usually got one.

RFC 6335 is new in that it reserves a port range to "will never be allocated, do as you wish but don't assume any port free". It's intended for services where the port number isn't assigned statically but kept in some registry.
Why 49152 as minimum port number? I can only guess, but I assume that some relatively important service already had 49151 already assigned to and they didn't want to revoke that assignment (until Aug 2011, there never has been a policy for revoking a port assignment).

This all was news to me, too :)


IANA has managed the low ports for a long time. No one pays attention to it in general other than to try to avoid often-used ports. The high ports are also sometimes called "ethereal ports". Since the beginning of TCP/IP time, they have been the ports that the networking layer can randomly assign to connections. Each end of a connection has to have a port. When you connect to an HTTP server somewhere, your local outbound socket needs a port. It grabs one from the ethereal ports because it does not care what port it is and it will be telling the other end (with a well known port) what port it is using.
@pspeed said:
You don't need to do this. You'd have to do it again and again in case of port conflict. It's WAY easier to let the networking layer find an open port for you by opening a server socket without a port. It will pick one from the ethereal ports (the high ones that you mention).

Edit: just open a ServerSocket, grab the port it's bound to and then close it again.


Just be aware of the race condition that could let someone else grab that port (highly unlikely I know but a bitch to track down if it ever does happen) and put in a retry loop or logging or similar.

@pspeed That ServerSocket approach looks nice, but does it restrict sockets to the allowed range? I’d really like to live in the unregistered area.



Also, you’ll need to retry with that code just as I do. Imagine several servers starting at the same time (actually not too unlikely if somebody does a game hosting server): There’s a race condition between getting a free port number from ServerSocket and starting the jme Server. If you wish to have a robust application, you need to retry until it works regardless of which approach you use.

I don’t think you’re right that “no one pays attention to [IANA]”, @pspeed.

There are a whole lot of people who pay really, really close attention to IANA’s policies, including port numbering. It’s usually those who do “serious” applications (for any of a number of definitions of “serious”).

Of course, whether “everybody” or “nobody” pays attention is largely a matter of the peer group you’re in.

Well, I’m ready to agree to disagree, but I definitely wish to have my port numbers in the “ephemeral” range. If SpiderMonkey cannot do that, it’s a less useful tool to me than it otherwise would be. (I have done a bit tracing through the networking code, and getting SM to actually autoselect a free port and pass that back to the caller would touch quite a lot of layers. I’m not sure if it’s worth the effort - but it sure would be nice to have it.)

@zarch said:
Just be aware of the race condition that could let someone else grab that port (highly unlikely I know but a bitch to track down if it ever does happen) and put in a retry loop or logging or similar.


The race condition would be rare since the ports tend to be handed out sequentially. The port you grab is burned for a while as soon as you grab it... at least in most implementations I've seen.
@toolforger said:
@pspeed That ServerSocket approach looks nice, but does it restrict sockets to the allowed range? I'd really like to live in the unregistered area.

Also, you'll need to retry with that code just as I do. Imagine several servers starting at the same time (actually not too unlikely if somebody does a game hosting server): There's a race condition between getting a free port number from ServerSocket and starting the jme Server. If you wish to have a robust application, you need to retry until it works regardless of which approach you use.


The ServerSocket approach is picking from the ethereal ports, ie: the unrestricted ports (because they CAN'T BE restricted). I'm really not sure how many different ways to say that.

You could go for decades without getting a collision this way. As I said, ports are handed out sequentially. You'd have to open many tens of thousands of connections before you'd have a real race condition. A network layer is not going to bother to hunt for and reuse an old port until it has exhausted its "nextPort++" ports.
@toolforger said:
I don't think you're right that "no one pays attention to [IANA]", @pspeed.
There are a whole lot of people who pay really, really close attention to IANA's policies, including port numbering. It's usually those who do "serious" applications (for any of a number of definitions of "serious").


It would be interesting to do a survey on how many games have ports registered in the IANA list. I've never seen one except some really low-numbered early id ports. But I haven't looked in a while. (Maybe it's changed. IANA used to manage a much smaller block.)

This is because most games (and most "serious applications") let you set the port yourself and the port they use is merely a default. If you get a conflict then you move it to a different port: problem solved.
@pspeed said:
The race condition would be rare since the ports tend to be handed out sequentially. The port you grab is burned for a while as soon as you grab it... at least in most implementations I've seen.

I agree. I just tend to be paranoid about things like that as I've spent days tracking down something "that will never happen" - both in my code and in other peoples. In my experience saying that X will never happen inside a computer program is in fact a prediction that it will happen, and usually at the worst possible time.

Heh. Nope. “Serious” applications have a registered port. Just take a look at /etc/services.

BTW what’s an “ethereal” port? I have never seen that nomenclature, and googling just tells me about ethereal the program.

The only difference I ever found was “high port numbers” vs. “low port numbers”, to distinguish between system and non-system ports - but let me repeat: that’s got nothing to do with assignment policy, only with the privileges required to open a port. (And with that new-fangled RFC 6335, there’s the “ephemeral” port number: ports above 49151.)



BTW some more googling found me Oracle’s Javadoc on the topic, which says that requesting a port with an unspecified port number will give an ephemeral port. I’m not sure that they really mean IANA’s definition of “ephemeral”, but at least that points in the right direction. (Heck, it would be okay if it followed the OS’ idea of ephemeral. That’s where the conflict occurs, anyway.)



That port numbers are assigned in ascending order… well, if it’s true, I bet that will expose a security issue one day and be randomized. At least that’s what happened to packet IDs, and I’m not far enough into network-related security to exclude this as impossible - which means I’m not going to depend on that.

Better code a retry loop than find my games suddenly mysteriously unstable because of a security update…

@toolforger said:
That port numbers are assigned in ascending order... well, if it's true, I bet that will expose a security issue one day and be randomized. At least that's what happened to packet IDs, and I'm not far enough into network-related security to exclude this as impossible - which means I'm not going to depend on that.
Better code a retry loop than find my games suddenly mysteriously unstable because of a security update...


I doubt that will ever become a security issue actually, but still the principle is sound.

In this sort of case running around a loop 3 (or even 10) times retrying the failure (and very importantly - logging what is going on) will take 5 lines of code and a few minutes of your time. With any luck it will never be needed but if it is ever needed then it will stop a really obscure bug that will either linger and annoy your users for a long time and/or take you ages to track down. Just don't use an infinite loop as that opens just as many problems in the other direction.

ephemeral is what I meant.



Regardless, randomly poking at port numbers is a poorer approach than logic that requests one from the OS… whether you wrap it in a retry or not. However, I will point out that the error (when it occurs) would be really really obvious… and about as rare as a class not found exception caused by disk corruption.