Hi Martin, Yes, you are right. With a string service, I could make the probability of clash very small with long random strings like UUIDs. * * * Sadly, back to today, where we are stuck with numbers, and numbers in the 16-bit numbers integers above 1024... :-) I see your recent commit does automatic re-try -- https://github.com/nanomsg/nanomsg/commit/52cc85c3d084ffb6d151927492584b94f3496797 But I'm still curious: What would happen if the initial failure to bind was distinguished and treated specially -- so as to handle cases when the port will never become available within a short period? Practically speaking, could we return an EADDRALREADYINUSE error when a port cannot be initially allocated? With the 52cc85 approach I believe we've just hidden the problem with a hang (forever re-trying) instead of an abort. Best regards, Jason On Sun, Nov 16, 2014 at 8:58 AM, Martin Sustrik <sustrik@xxxxxxxxxx> wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hi Jason, > > I am not sure why your use case cannot be implemented using string > service names. Just generate an UUID, use it as a service name and you > are pretty much guaranteed that you won't clash with another application. > > Martin > > On 16/11/14 17:22, Jason E. Aten wrote: > > I suspect we may be simply thinking about solving different > > problems, but I'll try to outline my use case below. > > > > Let's ignore the problems of using root-only ports (those below > > number 1024) for the moment, even though practically that does > > make depending on running a service on port 1 an impossibility in > > many situations. Also lets ignore strings versus ports, since that > > is just a size-of-the-namespace issue, and less fundamental. > > Let's focus on dynamic vs static port allocation. > > > > Static strings might work for servers (to use a phone analogy, > > where I'm a business and I want a listed number in the phone book), > > but static strings don't work for clients (exactly when I don't > > want to list my number, and in fact for security I may want an > > unknown-in-advance and/or unpredictable number). > > > > Example: When a client socket connect()s, it cannot reuse a well > > known port on the client end. So the tcp stack allocates the client > > a random, unused port. > > > > Whenever we have an analogous situation to that, then we'll need a > > dynamic port, no? > > > > * * * > > > > Keeping that analogy in mind, I see a separate set of use cases > > where a dynamically allocated port is required. > > > > My use case is that I have a simple job processing system with > > multiple worker processes on the same host. > > > > Each worker wishes to open a port to receive a reply message meant > > specifically for them. Since we wish to de-couple requests and the > > replies to those requests, each worker must have its own listening > > port. > > > > At their start, as workers request a job. As a part of that job > > request, say to a job-dispatching service, the worker tells the > > dispatcher where to send the job, in the form of an IP:port pair. > > > > In order to have multiple independent processes running on the > > same machine, and so replies go directly to the worker that > > requested that particular job, each worker must listen for replies > > on its own port. Since they can't all share the same port, they > > need to allocate a currently unused port. Really this is just like > > the socket connect() from the client example, perhaps generalized a > > bit. > > > > * * * > > > > Practically speaking, the re-try functionality of nanomsg is very > > important. But failure to bind a port even once at startup time is > > an initialization error that retry cannot solve automagically for > > us. We should distinguish and elevate a failure to bind a port the > > first time, so that applications using nanomsg can take appropriate > > remedial measures. > > > > It's rather kludgy to have to determine a port outside of nanomsg > > at the moment, because it has a built in race condition (the gap in > > time between when I ask the kernel for a socket and then release it > > and tell nanomsg to take that port). I suppose the other way > > things could work would just be to provide a way to tell nanomsg to > > use the socket that I've already allocated. > > > > > > Best regards, Jason > > > > > > > > On Sun, Nov 16, 2014 at 6:17 AM, Martin Sustrik > > <sustrik@xxxxxxxxxx <mailto:sustrik@xxxxxxxxxx>> wrote: > > > > -----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) > > iQEcBAEBAgAGBQJUaNeqAAoJENTpVjxCNN9YlV4IAJ3Nh5qkn8s+59CbvUOPFvIK > ERS2f4H/5v2qGsxDntoSgYdjLzHSiw0ilVL6E5e6B+cZQWeDw3nqvxFqtKWNISF7 > ypAVinWJOztTfmeocKPFKw2izrFwMh88epoAu3NDJN5PAwVEm2ay0LaOkaULJUeM > A1x+G9AShovHJ5zr0ixxmYQHrVnXD0fHUQuNv5I3cggumOrkg1l7AuGbIIfaJuQj > PDeecA7+KGAFlRLYCKsvAXRMek+gkBWIwsm0R0II/LUZrHDE+nTQX3mqR1QA7fdv > xWIX6QnyqWutcRNOpoF3BwDot1m2Zbtf5fwUFXhCmsQJFZrCmy1JS45IPJJ3flg= > =u6PR > -----END PGP SIGNATURE----- > >