LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Video transmission from one computer to another computer over TCP

Solved!
Go to solution

@alexderjuengere wrote:

using Client-Server.zip ‏131 KB from Mark's Message M1233232 with minor changes:

 

Spoiler

Server-v2.vi:

- renamed the second "send data" case in "Stop"

- linked typdef 'data' to 'C:\Program Files\National Instruments\LabVIEW 2020\examples\Data Communication\Protocols\TCP\TCP Multiple Connections\controls\TCP Multiple Connections Data.ctl' etc.


Client-v2.vi:
- removed imaq-vis to send empty images

proof of data transmission on both localhost and port 6341

1# start server-v2.vi via run button (and stop via FRontpanel ' stop Button' )

2# start client-v2.vi via run button

3# stop client-v2 via 'abort execution' button -  this will stop server-v2.vi, too (after clicking two times continue)

4# look at incremented "# of connections"

 

Spoiler
2022-07-13_mark.gif

 

now, modify to your needs

 

if you move from your 1 computer localhost setup to a 2 computer setup, I recomment to use the freeware https://iperf.fr/ to find valid port pairs

 

 


This is the first example I created.This kind of code does not meet what I want to do. Anyway, thanks for your answer. If you read my previous posts, I think you will understand what I mean.

0 Kudos
Message 41 of 64
(353 Views)

Finally I created the following Server and Client VI which does exactly what I want. I think I solved part of the problem.

I created a reconnectable Server and Client. In the next steps, I will add the video data again.

0 Kudos
Message 42 of 64
(343 Views)

@constructionworker wrote:

This is the first example I created.This kind of code does not meet what I want to do. Anyway, thanks for your answer. If you read my previous posts, I think you will understand what I mean.


whoospie 😉

0 Kudos
Message 43 of 64
(335 Views)

@constructionworker wrote:

Finally I created the following Server and Client VI which does exactly what I want. I think I solved part of the problem.

I created a reconnectable Server and Client. 


looks ok

 

Spoiler
 server-client.gif

although, I would save a copy of those .ctls somewhere near the .vi not in the C:\Program Files\National Instruments\LabVIEW 2018 folder

 

 


@constructionworker wrote:

In the next steps, I will add the video data again.


I wish you success

0 Kudos
Message 44 of 64
(331 Views)

There is absolutely no reason you should have a Wait On Listener in your client code. That is used in servers only. I don't know why you are abandoning the basic message protocol that I, and many others, have recommended you use. The implementation you have is not at all flexible or extendable. Will you ever have more than one client connecting? If not, why handle multiple client connections? If you will, are all clients going to be working in lock step with each other? Because as written, every client will always be treated the same and get the same data. Generally a server handling multiple clients will spawn individual tasks to handle each client connection. That way if one client has an issue only that task will be affected. As written, if you have one client that is very slow all of your clients will be affected because you send data to them sequentially. If you really do want to handle multiple clients I would have a dedicated listener task that only handles new connection requests. This would always wait using a -1 for the timeout.

 

This code is much better than your original posting. Not sure why you would ignore all the advice for much better implementations.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 45 of 64
(314 Views)

@Mark_Yedinak wrote:

There is absolutely no reason you should have a Wait On Listener in your client code. That is used in servers only.


-What I want to create is that if the client is shut down and restarted it should reconnect to the Server. Because in the next stages, there will be situations where only the client needs to be closed.


I don't know why you are abandoning the basic message protocol that I, and many others, have recommended you use. The implementation you have is not at all flexible or extendable.


-By basic communication protocol you mean; If the server is started, the client can be run, and if the server is closed, the client must be closed at the same time, right?

If you're talking about this, I explained above why I actually do it this way.

 

 Will you ever have more than one client connecting? If not, why handle multiple client connections? If you will, are all clients going to be working in lock step with each other?

 


Although it is unlikely that more than one client will be connected at the moment, I left some doorway for multi-client connection in case I can add it in the next stages.

 


Because as written, every client will always be treated the same and get the same data. Generally a server handling multiple clients will spawn individual tasks to handle each client connection. That way if one client has an issue only that task will be affected. As written, if you have one client that is very slow all of your clients will be affected because you send data to them sequentially. If you really do want to handle multiple clients I would have a dedicated listener task that only handles new connection requests. This would always wait using a -1 for the timeout.

 

This code is much better than your original posting. Not sure why you would ignore all the advice for much better implementations.

 


I do not prioritize multi-client usage very much at the moment. But if I start using multi-client, I think it cannot be done with the current code, too many changes may be required.

Actually, my main focus right now is just creating reconnectable server and client.

 

By the way, I used the "creat listener" that I created in the "initialize" state in Server VI and the "Wait on listener" that I used in the "Status check" state to reconnect. 

Likewise, in Client VI, I used "TCP Open connection" for "Open connection" and "Wait on Listener" for "Check connection" to create a reconnectable connection.

 

I don't know if there is another method.

 

I am trying to improve the code as far as I understand, taking into account the suggestions made.

I couldn't solve your problem because I couldn't fully understand the fix you shared.

I must say I understand a lot from your fixes, but I can't find the exact source of the problem.

 


0 Kudos
Message 46 of 64
(303 Views)

Only servers have a listener so a Wait on Listener is only valid in a server. If you want the client to reconnect you have to first detect an error on the connection. This is very straightforward since any read/write will return an error is the connection is lost. Once a client detects this it would enter the reconnecting state. I recommend that both the client and the server use a basic state machine to control the flow of the application. Anyway, the client would continually try to establish a connection with the server using Open TCP Connection. If the open is successful change states and do what ever processing is to be done when it is connected. If the open fails, go back and try again. Rinse, lather repeat. Depending on your requirements you may do other things such as capture the image from the camera even if not connected. Whether you do that or not depends on your particular needs.

 

Given that you are struggling with getting a single client to work I would avoid adding multi-client support to the server at this time. That only complicates things and as I mentioned earlier, the way you handle clients now could dramatically impact performance for all of your clients if one becomes sluggish for some reason.

 

When I say a basic message protocol it is what I explained earlier. Rather than simply sending a Q as you message (which has issues for several reasons which I will explain later) you are better off creating a simple message format. I had suggested that your message format would consist of a message type (defined as a number), a data length (which can be 0) and the data field. If a particular message has no data your message header (the ID and length) would be the message ID and a 0 for the length. That indicates  that no data follows and the entire message is contained in the message header. This way your reader always reads a fix amount of bytes (the size of your message header). Then it can check if there is more data and using the length field it knows exactly how many bytes to read. This makes your message processing very flexible and expandable.  Your message ID could be a string but that introduces other issues unless your string ID is a fixed length. In your first code you posted the client sent two images back to the server. However there was nothing in your data stream that indicated how long each image was, if it was an image, which image was it, etc. All you had was a stream of bytes with no explicit knowledge of knowing what they are or what they represent.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 47 of 64
(296 Views)

@Mark_Yedinak wrote:

Only servers have a listener so a Wait on Listener is only valid in a server. If you want the client to reconnect you have to first detect an error on the connection. This is very straightforward since any read/write will return an error is the connection is lost. Once a client detects this it would enter the reconnecting state. I recommend that both the client and the server use a basic state machine to control the flow of the application. Anyway, the client would continually try to establish a connection with the server using Open TCP Connection. If the open is successful change states and do what ever processing is to be done when it is connected. If the open fails, go back and try again. Rinse, lather repeat. Depending on your requirements you may do other things such as capture the image from the camera even if not connected. Whether you do that or not depends on your particular needs.

 

Given that you are struggling with getting a single client to work I would avoid adding multi-client support to the server at this time. That only complicates things and as I mentioned earlier, the way you handle clients now could dramatically impact performance for all of your clients if one becomes sluggish for some reason.

 

When I say a basic message protocol it is what I explained earlier. Rather than simply sending a Q as you message (which has issues for several reasons which I will explain later) you are better off creating a simple message format. I had suggested that your message format would consist of a message type (defined as a number), a data length (which can be 0) and the data field. If a particular message has no data your message header (the ID and length) would be the message ID and a 0 for the length. That indicates  that no data follows and the entire message is contained in the message header. This way your reader always reads a fix amount of bytes (the size of your message header). Then it can check if there is more data and using the length field it knows exactly how many bytes to read. This makes your message processing very flexible and expandable.  Your message ID could be a string but that introduces other issues unless your string ID is a fixed length. In your first code you posted the client sent two images back to the server. However there was nothing in your data stream that indicated how long each image was, if it was an image, which image was it, etc. All you had was a stream of bytes with no explicit knowledge of knowing what they are or what they represent.


I understand you. But I'm trying to figure out exactly how to do it. I have doubts especially in sending and receiving ID and message length. But I couldn't solve the problem. Do you have a chance to try the sample on your own?
There seems to be a logic error in particular here.
I tried to explain in the photo below.

 

Test.png



0 Kudos
Message 48 of 64
(275 Views)

Ok, so I see the basic issue. Create a new typedef and call it "Message Header". This typedef should contain the message ID and length. Modify the message typedef to use the new header typedef. Make sure that the order of the cluster is that the message header cluster is the first element of the cluster and the data field is the next item in the cluster. In the receive message VI replace the typedef wired to the unflatten from string to use the new header typedef. This should correct the issue that you are seeing.

 

Note: I am not at a computer that I can update the code for this post. If you still have issues I can post an update later. The current client code would need to be re-worked to support the auto-receonnect.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
0 Kudos
Message 49 of 64
(257 Views)

@constructionworker wrote:

@Mark_Yedinak wrote:

Only servers have a listener so a Wait on Listener is only valid in a server. If you want the client to reconnect you have to first detect an error on the connection. This is very straightforward since any read/write will return an error is the connection is lost. Once a client detects this it would enter the reconnecting state. I recommend that both the client and the server use a basic state machine to control the flow of the application. Anyway, the client would continually try to establish a connection with the server using Open TCP Connection. If the open is successful change states and do what ever processing is to be done when it is connected. If the open fails, go back and try again. Rinse, lather repeat. Depending on your requirements you may do other things such as capture the image from the camera even if not connected. Whether you do that or not depends on your particular needs.

 

Given that you are struggling with getting a single client to work I would avoid adding multi-client support to the server at this time. That only complicates things and as I mentioned earlier, the way you handle clients now could dramatically impact performance for all of your clients if one becomes sluggish for some reason.

 

When I say a basic message protocol it is what I explained earlier. Rather than simply sending a Q as you message (which has issues for several reasons which I will explain later) you are better off creating a simple message format. I had suggested that your message format would consist of a message type (defined as a number), a data length (which can be 0) and the data field. If a particular message has no data your message header (the ID and length) would be the message ID and a 0 for the length. That indicates  that no data follows and the entire message is contained in the message header. This way your reader always reads a fix amount of bytes (the size of your message header). Then it can check if there is more data and using the length field it knows exactly how many bytes to read. This makes your message processing very flexible and expandable.  Your message ID could be a string but that introduces other issues unless your string ID is a fixed length. In your first code you posted the client sent two images back to the server. However there was nothing in your data stream that indicated how long each image was, if it was an image, which image was it, etc. All you had was a stream of bytes with no explicit knowledge of knowing what they are or what they represent.


I understand you. But I'm trying to figure out exactly how to do it. I have doubts especially in sending and receiving ID and message length. But I couldn't solve the problem. Do you have a chance to try the sample on your own?
There seems to be a logic error in particular here.
I tried to explain in the photo below.

 

Test.png




See, that is the beauty of having a standard header with the length (which you calculate before sending) of the rest of the message.  You read the header - which is a known length - parse the length field, and read that many more bytes.  You can get fancy and add some kind of checksum if you are paranoid about data integrity, too.

Bill
CLD
(Mid-Level minion.)
My support system ensures that I don't look totally incompetent.
Proud to say that I've progressed beyond knowing just enough to be dangerous. I now know enough to know that I have no clue about anything at all.
Humble author of the CLAD Nugget.
0 Kudos
Message 50 of 64
(254 Views)