[nanomsg] Re: How to bind on a random port?

  • From: Martin Sustrik <sustrik@xxxxxxxxxx>
  • To: nanomsg@xxxxxxxxxxxxx
  • Date: Sun, 16 Nov 2014 15:17:51 +0100

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 16/11/14 05:45, Matt Howlett wrote:
> It should be treated as a failure to connect. The implementation 
> should try to re-connect assuming that the interface will become 
> available eventually.
> 
> 
> I think it would be very common for people to want an atomic way
> of checking if a port is free, binding to it if it is, and moving
> on if it is not (I want this and I notice a number of others here
> do too). I also think that in most scenarios where a port is
> already in use, it's likely to stay that way for a time period long
> enough that the application wanting to bind to it is not going to
> find it useful to wait for it to become free (I'm not an expert
> though and could be missing a common scenario where this
> functionality is actually useful - examples?). So based on that, I
> think the former behavior is the best, or should at least be an
> option.

Ok, let me give you the big picture.

Long ago the authors of Internet protocol suite have decided to use
16-bit integer IDs to address different "services" on a host. I guess
back then the decision must have seemed reasonable, but later on it
became clear that the namespace is too small and the service often
clash using the same ID (port).

In 1988 there was an attempt to solve the problem (at least for TCP)
by defining a protocol that used arbitrary string as IDs instead of
integers (TCPMUX, RFC 1078, TCP port 1) but it never got wide adoption.

If you think of it, using strings solves the problem fully. You can
use fully qualified name as a service ID, it can contain the name of
the vendor etc. In such world there's would be no service name clashes
and thus no need for dynamically assigned service IDs.

Unfortunately, TCPMUX was ignored and instead everybody sticks to port
numbers and hacks around the problem using dynamically assigned ports.

Yet, dynamically assigned IDs are a spectacularly bad solution:

1. The dynamically assigned ID has to be somehow communicated to the
peers in runtime. That adds whole new layer of complexity to the
applications.

2. Given that service IDs change as the services are restarted,
there's no way to define service-specific policies at network level
(e.g. allocating 100MB/s of bandwidth for service X).

3. The solution is prone to inconsistencies and race conditions, with
different nodes having different ideas about what the ID of service X
happens to be. You can think of it as a very simple distributed
database which means you have to deal with CAP theorem: Either you can
always determine the port number to use (Availability) or everybody
can agree on the same number (Consistency) -- bet never both.

In context of nanomsg (which does automatics reconnecting) the problem
becomes even more pronounced: Say you bind to a wi-fi interface, get
port X assigned, then the interface goes away (you are out of range of
the wi-fi), then becomes available once more. You can try to re-bind
to the same port, but it may already be taken. You can ask for a new
dynamically allocated port but then it's certainly going to be
different from the old one. The change would have to be communicated
back to the application. How? Callback? And even if so, what would
application do in such case? Et c.

The bottom line is the we should rather than using dynamically
assigned ports we should rather using string-based service names. I
was thinking of actually implementing TCPMUX, but the idea surfaced
again yesterday when speaking of WebSocket transport and using
WebSocket URLs basically as service names.

Well, that's more or less it. Sorry for the long rant but I hope it'll
explain why things are done as they are and what is my preferred
solution to the problem of service ID clashes.

Martin





-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)

iQEcBAEBAgAGBQJUaLIPAAoJENTpVjxCNN9YIfoH/R38pX4NqwoxafShyYzzgiXQ
BSkMgF/lRpWD1MZwkJxPLG0lfbIiZioGNn0Zhy3fEyEkxqkSfbS12IvOrJ02XmYH
cg4WPFAOIu9EKfgJdUC3OQaa7vXVdB+M5QEEAWInCPffNGUTudmd3GXYsfix6ml6
7HBpDnV0e8cpGie6xpRPsWNxl7k/6o7a5hEHhgqdZDeI2w1NjON7J2VN1eH8mkBP
+Y4vsXeOgHIKpGd5XXmC+65KV82sZkzxMeTkeGDa/F08VpAdDA84htHeW/VcZZCi
TDZ7+YROKoWECAmC3XDRMVtpXMUYHZWFJVivULigxyQLPmJkW1mPtKzaKVjEkow=
=mcjQ
-----END PGP SIGNATURE-----

Other related posts: