How to communicate the port for AutoDiscovery

I agree with you and that’s not the way I would write it, however this is sample code and supposed to be simple.

Sample code is only simple if it does not lead a reader down the proverbial garden path …

… after all, there are different ways of being wrong.

Nope, that’s not work using dynamic ports works. If you want a fixed port, you need to use one below 8192. Any ports above 8192 are dynamically assigned just like shown in the (buggy) loop. And it’s not slow. The system knows which ports are in use, so you’ll immediately get a response (i.e. exc.) if the chosen one is not available.

Dynamic ports are to be used when you have a way to respond to the other side (e.g. when the other end contacts you first via a known port on which you listen, and then you create a new connection with a random port that you communicate back), or when you use something like zeroconf (bonjour) to share your port on the network. Fixed ports are a bit of a problem in larger networks because the port may already be in use.

The other “bug” in the loop is to catch a RuntimeException. In this case, it should instead be catching the particular exception thrown by Bind. Because if you catch 'em all, you may also catch an attempt to quit the app or kill a thread (if you call its Kill method), and then the quit/kill would be stopped.

3 Likes

Markus. The bug is that when the Bind fails once, then success will remain false even if the next Bind succeeds - and that’s how you end up with an endless loop. That’s the bug.

1 Like

Yeah, looks cleaner. However, keep in mind that Xojo had bugs in the past where early exits (including using goto) did not release all objects, and you’d end up with leaks :slight_smile: Hopefully all sorted out by now, though.

The optimized code does exactly that, do not allocate anything. But besides that, what you are saying is such a primary bad compiler design that I can’t believe it survived a Joe Ranieri review of a scope block.

I / Me / Myself (and also Irene) know that … :slight_smile: … I think you are confusing me with someone else here … :wink:

But thanks for your detailed explanation about finding a common port - I did not know THAT :blush:

BTW, I have editing permissions to the docs, so I could fix the example.

However, when I tried this out, I found several issues:

  1. I can Bind to any port, even 80, and not get an exception (tested on macOS with Xojo 2019r3.2, both 32 and 64 bit)
  2. I cannot find the AutoDiscovery class in the Library in order to add it to a window. Neither is EasyTCPSocket in there. So I had to add some other random control and modify its super. There used to be a “Object” type for that in the older IDE - now there’s only “Class”, but when trying to add that, it won’t get added to the Window - I then have to drag it into the window. What a mess.
  3. AutoDiscovery has no Open event. But the 1st code example uses “me” to refer to the AutoDiscovery object. From which even would one do that, then?

Friggin hell! This is supposed to be a beginner’s development system. That should mean it’s for beginning programmers, not, as it appears here, written by beginners.

Does anyone have a working example using AutoDiscovery? If so, send that to me, and I’ll use that as an example to update the docs.

Update: It appears that instead of throwing an exception, it simply sets the “isConnected” property. That’s what you have to check when trying to Bind. Also, code completion does not offer any “last error” property, yet it shows the constants for various errors. Mess.

3 Likes

FWIW, in Unix systems the the first 1024 ports are privileged ports and only root can bind to them. If you are using a regular user account I find unusual a MacOS to bind to 80.

1 Like

:popcorn::popcorn::popcorn:

2 Likes

My point was that even though I used a port that surely can’t be used (as you know), I didn’t get an exception as the code suggested.

2 Likes

I’ve now confirmed that IsConnected is the way to check whether the Bind worked.

Also, with the Unix command lsof -i -P -n | grep "AutoDis" one can see where AutoDiscovery has bound to.

Sadly, though, it does not use Zeroconf (which I verified with the app “Bonjeff”, which is a Bonjour browser).

I believe (not tested) that while you’re only trying to communicate to other apps on the same computer, AutoDiscovery will find your “group” automatically, i.e. you do not have to know the port, but just the group name. Only when you want to be reached by other computers on the same network, you’ll have to publish your used port somehow, or use a fixed one that can be easily configured in case it’s already in use by something else on the network.

2 Likes

That’s, kind of, unusual too. It should be like IsBound, and “connected” reserved to peers (devices).

1 Like

Rick, but AutoDiscovery has no IsBound property, or does it?

1 Like

Actually, I don’t understand why one needs to Bind at all. Binding is needed when using a UDP/TCPSocket in which you want to do the communication yourself.

But AutoDiscovery, per its declared ability, does the comms itself. And it appears, when looking with the lsof cmd, that it already opens its own ports.

After some more testing I’ve figured this out:

  1. Every app (on the same computer) needs to use its own port. So, the port that is randomly chosen should not be made a fixed one, because if you run two apps on the same computer and they want to communicate with each other via AutoDiscovery groups, they need to Bind to different ports, or they can’t communicate with each other. I think this is a bad design, because this class should take care of this detail itself.
  2. For communication between different computers, this class is quite useless. You can just as well use EasyTCPSocket, because AutoDiscovery in that scenario.

Huh, well: The docs for AutoDiscovery explicitly say that it should work for sharing between multiple computers, just like Zeroconf does.

I’ll do some more testing.

Looking at the AutoDiscovery project in the Xojo Examples folder shows another “bug”: It uses a fixed port (9090), i.e. it does not try to find one that’s available.

This is why I don’t like to work or recommend Xojo any more: It’s so fokked up even though it could be much better if it were not for the poor quality, support and direction (trying to do more than they can handle).

Update

Just as I thought: The docs are again totally misleading. They suggest:

The AutoDiscovery class lets you automatically discover other machines on the local network

However, this only works on the same computer, but not over the LAN. Because this is not working like Zeroconf. At least not when trying this with Macs.

The AutoDiscovery example project only works between different computers because it’s using the same port number on all.

Even worse: If you’d fix the code to dynamically assign an available port on each computer, this class is missing a way to say: Hey, the other computer is using port Y, so please send the message to its actual port. This isn’t working because this class wants to pass messages to the same port it uses on its own end. Which is totally wrong.

So, basically, this class is, despite its mistaken claim, only useful to communicate between apps on the same computer, with automatically detecting them (provided you dynamically assign the port number).

For inter-computer messaging, it’s useless in a real environment where you cannot guarantee that the port is available. – The example is even doing that wrong because it uses a port number above 8191 - those ports may be used by other app at any time (e.g. by Safari when loading a web page), so you must never use such ports with fixed numbers. The only safe way here would be to use a port between 1024 and 8192. And the app, when using one of those, needs to check whether it can actually use it, and alert the user if it#s not available. so that the user then configures all copies of this app on the network to use a different common port number between 1024 and 8191.

The best solution, however, would be to stay away from this badly designed class and instead:

  • Use another socket type, e.g. EasyTCPSocket
  • Dynamically Bind to a port >= 8192
  • Share the bound port number via Zeroconf / Bonjour. I’m sure there are solutions out there for Xojo for all platforms.
5 Likes

I think they never tested that thing. They can’t even document it properly because of that. And this line from the docs says it is useless for the average user “the other member of the group must then use the same port, so you need to find a way to communicate this port to the others”. The AutoDiscovery class seems a project prematurely released before completed, if it says it does not have an announcement service set in place (not necessarily bonjour, any announcement/binding broadcasting service integrated) at the end it does nothing like an “autodiscovery” service, it does not discover anything.

2 Likes

You know we have Bonjour classes in MBS Plugins for reasons.

2 Likes

I see they (or you) changed the binding example to

Do
  AutoDiscovery1.Bind(Rnd * (65536 - 8192) + 8192)
Loop Until AutoDiscovery1.IsConnected

But what happens if you just do:

  AutoDiscovery1.Bind(0)

This is the usual “Dear OS, bind me to a free proper port”.

What is going on?
Can’t I mentioned a plugin as alternative to AutoDiscovery?

6 Likes

Your post was flagged by the community. I disagreed with the flag in this case and have restored your post.

2 Likes