LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

TCP Connection: send data from CVI Client to LabView Server

Hi!

 

I have big issues establishing communication over TCP between client app written in CVI and server written in LabView.

First, I created client app in LabView and communication worked fine. In attached picture ‘from_labview_client.jpg’ I pictured server behavior when app was sending two portions of information: first -  number of bytes to read in next TCPRead, second – actual information containing measure parameters (three doubles: 2.00, 2.00, 2.00 in cluster). I also attached LabView client block diagram (client_labview.jpg) so you could see how it works.

 

Then I wanted to achieve the same results using client app written in CVI. As you can see (from_cvi_client.jpg), in the second ClientTCPWrite I struggle to send data in the correct form - I tried sending cluster, but probably I'm doing it somehow wrong.

Could you please help me and point where I make mistake and how to correct it? How to get rid of null values in the beginning of second data out? How to properly cast doubles/cluster to ASCII?

 

Here is my callback function to send data from client to server:

static unsigned int g_hconversation;  
static double n_steps;
static double max;
static double min;

int CVICALLBACK start (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{   
	char paramy[4];

	switch (event)
	{
		case EVENT_COMMIT:
			
			 GetCtrlVal (panelHandle, PANEL_NUMERIC, &n_steps);  //getting values from numeric to variables
			 GetCtrlVal (panelHandle, PANEL_NUMERIC_2, &min);
			 GetCtrlVal (panelHandle, PANEL_NUMERIC_3, &max);
			 
			 typedef struct params params;		  //struct definiton
			 struct params{
				 double min;
				 double max;
				 double n_steps;
			 };
			  
			 struct params struktura;                       // struct initialization
			 struktura.n_steps = n_steps;
			 struktura.max = max;
			 struktura.min = min;
			 
   			 
			 SetWaitCursor (1);
    int err = ConnectToTCPServer (&g_hconversation, 6341, "", ClientTCPCB, 0, 5000); // establish connection
		

	if(err<0)
		{
		MessagePopup("TCP Client", "Connection to server failed !");	
		break;
		}
    else
	
        {
		printf("CONNECTED\n");
		

		paramy[0] = 0;
		paramy[1] = 0;
		paramy[2] = 0;
		paramy[3] = sizeof(struktura);
		
		err = ClientTCPWrite (g_hconversation,&paramy ,sizeof(paramy), -1);  
		
		
		err = ClientTCPWrite (g_hconversation, &struktura,sizeof(struktura), -1);
		}

			break;
	}
	return 0;
}

 

Thanks in advance!

0 Kudos
Message 1 of 6
(5,313 Views)

A start of a solution but not all ... I see something that I (as amateur) do not recognize as valid.

 

With respect to you question ... you send the structure as a binary block.

The TCP function gets a pointer to that block. If you get a warning, you can cast is e.g. (unsigned char *)&struktura

 

One line before, you send the char array. That is what I do not understand.

You have a 4-byte character array paramy. So paramy itself is a pointer to the start of this array. Or &paramy[0] is the same pointer. But &paramy is the address where the pointer is stored. Still you get receive the value 24 at your server. So it seems ok ...

 

Unknown for me is labview ... what is the byte-order that labview expects. 

And is this the same for client and server

<http://en.wikipedia.org/wiki/Endianness>

 

One answer for the next problem and before the professionals take over ... be careful when you extend the structure.

Labwindows will have a default for packing data in a structure that probably depends on operating system.

<http://digital.ni.com/public.nsf/allkb/F7E5C9169D09E98586256AF300717B33>

I set at the start before defining the structure: #pragma pack(2)

Next: typedef  the structure where all character arrays have even length or single bytes are followed with dummy byte

I end after the structure definition with: #pragma pack()

 

 

Succes, Jos 

Message 2 of 6
(5,283 Views)

P.S.

When reading back my reply, I see (besides all the typing errors) that the second link is lost:

Search for: labview packing

Find article with title: Clusters in LabVIEW Do Not Line Up With Structures in Visual C++

 

Message 3 of 6
(5,262 Views)

First of all,

I would make the struct definition as below and put it outside the callback.

typedef struct _params {
  double min;
  double max;
  double n_steps;
} params;

Second,

ClientTCPWrite does not guarantee that all bytes are written in a single call.

You have to call it in a loop until all bytes are sent. See the function help. There is a sample code there.

 

Third,

JGS is right about byte orders and struct packing.

To make sure your struct's size is exactly same as what you expect, type #pragma pack(1) at the top of your file.

Look up "struct packing" to learn more about the subject.

 

If you are sending binary structures by using their pointers, client and server applications must agree on the orders of bytes.

This is called "Endianness" and it depends on your hardware (CPU). Make sure client and server has the same endianness.

x86 family of CPU's are all little-endian.

 

Hope this helps,

S. Eren BALCI
IMESTEK
Message 4 of 6
(5,195 Views)

Note also that whilst Intel x86 & x64 architectures, and CVI on PC, are all little-endian LabVIEW is big-endian - so passing binary data to LabVIEW from almost anything else requires byte reversal at some stage.

--
Martin
Certified CVI Developer
Message 5 of 6
(5,182 Views)

Thanks for all your replies!

As programming in CVI and LabView is new to me, all your suggestions were really helpful and guided me towards solution 🙂

In the end, I decided to modify my LabView server and added 'Reverse string' blocks and reversed order of values in paramy array.

Thanks to this, server correctly reads both data in paramy array and data sent in struct.

 

 

0 Kudos
Message 6 of 6
(5,170 Views)