Jump to content

Remote messaging method with only server side connections


Recommended Posts

I need to find a transport for message objects that allows two way communication without polling but is limited to server side connections only.  So, the client can connect to the server but the server cannot connect to the client.

First some context:  My application communicates over the network using VI Server.  My client app (the UI) opens a ref to a VI in my server app (the engine) and sends a message object containing the client app’s machine name and VI server port.  The server app then opens a ref to a VI in my client and sends a message object with the reply data.  I now have a two way communication channel via VI server and can pass any message object back and forth without polling.

I learned today that our IT department plans to block all incoming connections to all non-server machines in the future.  So, my client would still be able to connect to the server app within the network, but the server would not be able to connect to the client app because of this rule.  This will completely break my networked messaging system.  I do not know a way for LabVIEW to setup VI Server so only one end can connect to the other but allow two way communication without polling.

 

Does anyone use a message system that would work in my situation?  I would prefer to continue to use VI Server but I am willing to look at other solutions, as long as they were very robust and had low latency.

 

thanks in advance for you help.

 

-John

Link to comment

That sounds a lot like how standard TCP works - one side is the server, the other is the client, and once a connection is established they can communicate in both directions. To avoid polling you can do a TCP read with a forever timeout, although this can lead to situations where a connection stays open forever even though it was interrupted somewhere. Another option is to poll in a separate loop - it's not much overhead - and when a message arrives, put it in a queue (or whatever) so that there's no polling from the perspective of the rest of the code.

Link to comment

Yes, I thought of using plain TCP but I did not want to invent my own wheel if possible.  And I could not think of a way to avoid polling.

The connection must be robust so it can deal with dropped connections and not lock up.

I also need to serialize my message objects in order to send them.  I am concerned with the overhead this might entail.  I have the VI Server solution working well right now with decent responsiveness.

 

Is there a good LabVIEW messaging library out there that uses TCP and would support sending objects?

Link to comment

Is there a good LabVIEW messaging library out there that uses TCP and would support sending objects?

As for the sending of objects, I've sent objects over TCP using Flatten to String in LabVIEW 8.6. I had to send the size of the flattened object string before sending the flattened object for it to work as there wasn't a termination character I could use.

Link to comment

I think I am going to be out of luck solving this one, but can anyone think of a way for a LabVIEW EXE (call it app1) to call a VI on remote machine running a different LabVIEW EXE (call it app2) without app1 knowing the IP or name of the machine running app2?

What I need to do is allow VI Server to call a VI where the application with the VI being called has opened the connection to the caller.

So, the client needs to open a VI Server connection to itself and then allow the server to call VIs in the client using that connection.

 

I know it sounds impossible, but I was hoping there was some hack or some unique way of achieving this through some other means.  I do not want the client to poll.  The server needs to push the data to the client when the server is ready.  The client needs to be able to accept the data at any time.  And the data needs to be a LVOOP object.

 

-John

Link to comment

You need the IP to create a TCP connection (which is what I assume you want). You can broadcast a message over UDP from app2 to app1; this is like shouting "I am here!" over the network. That broadcast can provide the IP to 'register' app2 with app1.

Link to comment

Unfortunately, that won't fix it.  The problem is not having app1 (the server) discover app2 (the client).  The problem is our network security blocks all connections from a server to a client.  So, it is fine for a client to initiate a connection to a server, but the server can never connect back.  Apparently this would lead to an insecure network so it is not allowed.  (personally, I think this is more due to insecure IT people, but either way it is out of my control).

 

So, I am trying to think of a way for the client to open a connection, leave it open without polling on it and allow the server to use that connection to send a message to the client at any time.  I would love to still use VI Server because it eliminates the need to worry about flattening data, but if that won't work, what is the next best thing? 

Link to comment

OK, I understand your question now. Yes, you can have app2 initiate a TCP connection and leave it open. app1 just has to listen for the connection. Either side can write to a TCP connection once it's open. The connection will stay open so long as nothing breaks it. The client will have to poll for new data... there isn't a way around that with communication.

Link to comment

Again, you don't really need to poll (or you can poll really slowly). Use a very long timeout on TCP Read, at least on the client, in a separate loop, and if data arrives before the timeout then execution resumes immediately (like waiting on a notifier). On the server side, if you don't want to poll and you do need to handle multiple connections, you can dynamically launch a new VI to handle each new incoming connection.

 

You may want to look at whether your network allows active FTP, since in that case the FTP server also establishes a connection back to the client. If the network has a rule that allows active FTP, then they may be able to add a similar rule for you (or perhaps it won't even be necessary) in which it will allow a connection from a server to a client only after establishing a connection from client to server.

Link to comment

In my current design, VI Server is my listener, always waiting for a connection.  The caller simply runs a VI in the receiver and injects a message onto the receiver's message bus.  So, both sides are callers and receivers.  It is basically a peer to peer messages system.

If I were to give up on VI Server, I would need to find a way to send my messages (LVOOP objects) over the alternative transport (TCP?).  I could flatten them to XML but not JSON as the built-in flatten to JSON functions don't work with objects.

But as you point out, the client would have to open a connection to the server, send it what ever commands it wants to send, then sit and listen for responses in a loop.

Since both applications are based on an Actor design (not AF) they need to not be blocked while waiting for messages.  This will mean coming up with some way to keep the listener in a separate thread that can hear messages, while at the same time still being able to send message to the server on the same channel.  And be able to abort the listener when the app shuts down.

Oh, and the server must allow N clients to connect to it at the same time.  And it must be able to reply to any of them or all of them at any time.  With little if any latency.

It just kills me that I get all this with VI Sever and now I can't use it...

Link to comment
Unfortunately, that won't fix it. The problem is not having app1 (the server) discover app2 (the client). The problem is our network security blocks all connections from a server to a client. So, it is fine for a client to initiate a connection to a server, but the server can never connect back. Apparently this would lead to an insecure network so it is not allowed. (personally, I think this is more due to insecure IT people, but either way it is out of my control).

So, I am trying to think of a way for the client to open a connection, leave it open without polling on it and allow the server to use that connection to send a message to the client at any time. I would love to still use VI Server because it eliminates the need to worry about flattening data, but if that won't work, what is the next best thing?

Websockets were created to resolve this sort of problem since browsers do not allow incoming connections (websockets create a bi-directional TCPIP connection). Some of what you describe is a little confusing to me since you talk about "discovery" and "polling" but that has little to do with TCPIP since you must know the IP address and labview isn't event driven (so must poll).

You can try it and see if websockets do what you need by running the demo on the server and using your browser to .connect ala these examples. When you have installed the Demo on the server, just navigate to the examples website and change the IP address in the example pages for that of your server.

Edited by ShaunR
Link to comment
If you have VI Server on both sides, you can avoid polling, at least in your code.  I do not know if you consider VI Server waiting for incoming connections as polling.

I will look into web sockets.  For some reason, the links in you message just take me back to this LAVA post.  Weird.

Hmm. The quick reply seems to screw things up.

 

Here they are again:

 

Websocket demo

Examples

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.