Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   Programming (http://www.chiefdelphi.com/forums/forumdisplay.php?f=51)
-   -   TCP problems in C# (http://www.chiefdelphi.com/forums/showthread.php?t=121892)

Invictus3593 19-11-2013 09:34

TCP problems in C#
 
I've got a small LV TCP server program writing a string to the stream and then on the client side (written in C#), when I read the stream every 20ms, it comes back jumbled after the first read.

For instance, if I wrote a string "a b c" to the stream, it would read like something this for the first four iterations (each line is what is read at 20ms):


Quote:

"a b c"
" ca b"
"b ca "
"ca b "


Here's the server code, really simple LV server, went off a youtube tutorial


Here's the C# code:

Code:

private void timUpdate_Tick(object sender, EventArgs e)
        {
            //update revolutions X and Y and the Gyro Angle every 20ms from the server string value
            //and make sure the connection is solid, otherwise update connection
            Byte[] info = new Byte[Client.ReceiveBufferSize];
            try
            {
                int rData = stream.Read(info, 0, System.Convert.ToInt32(Client.ReceiveBufferSize));
                RobotData = System.Convert.ToString(rData);
            }
            catch (System.IO.IOException)
            {
                lblConnectInd.BackColor = System.Drawing.Color.Red;
                Log("The robot ended the stream.");
                stream.Close();
                Client.Close();
            }

            //split string into X, Y and angle
            strRevX = RobotData.Substring(0, 2);
            strRevY = RobotData.Substring(5, 2);
            strAngle = RobotData.Substring(8, 2);

            //update values recieved in GUI
            lblX.Text = strRevX;
            lblY.Text = strRevY;
            lblAngle.Text = strAngle;

            //convert separated strings into doubles
            Double.TryParse(strRevX, out dblRevolutionsX);
            Double.TryParse(strRevX, out dblRevolutionsY);
            Double.TryParse(strAngle, out dblAngle);


            //make sure we're still connected
            if (Client.Connected == true)
            {
                lblConnectInd.BackColor = System.Drawing.Color.Green;
            }
            else
            {
                lblConnectInd.BackColor = System.Drawing.Color.Red;
                timUpdate.Stop();
            }
        }

Does anyone know how to fix this or what I'm doing wrong? I need a quick read time to get accurate data..

Alan Anderson 19-11-2013 11:05

Re: TCP problems in C#
 
I'm having a hard time understanding what you want to do. What you're calling the "server" is apparently sending data continuously, and what you're calling the "client" is apparently reading the accumulated data once every 20 milliseconds. Is that the intent?

Normally, I'd expect the client to send a packet of data either on a fixed schedule or whenever the data is available, and the server would wait for data to appear before reading it and processing it immediately.

Joe Ross 19-11-2013 12:02

Re: TCP problems in C#
 
The first thing you should do is use a program such as wireshark to capture the TCP/IP packets and determine if they are being sent as discrete packets. TCP is a stream protocol and guarantees that things will be received in the correct order, but they may be packetized differently then you expect. You can learn more by searching for nagle algorithm.

Why are you sending data with no delay in LabVIEW, but reading data every 20ms? You'll probably fill up the TCP/IP buffers fairly quickly.

RyanCahoon 19-11-2013 23:28

Re: TCP problems in C#
 
Quote:

Originally Posted by Invictus3593 (Post 1303352)
Here's the C# code:

Code:

Byte[] info = new Byte[Client.ReceiveBufferSize];
int rData = stream.Read(info, 0, Client.ReceiveBufferSize);
RobotData = System.Convert.ToString(rData);


It doesn't match the symptoms you're reporting, but I think you want

Code:

RobotData = System.Text.Encoding.Default.GetString(rData);
The code you have is extracting data from rData formatted as a string, where rData is the number of characters read from the socket stream. The actual data read from the stream is stored in info, which you aren't currently using

Invictus3593 20-11-2013 09:18

Re: TCP problems in C#
 
Thank you guys for the replies!

I have to admit, I'm just learning TCP so please excuse any noob-ish mistakes I've made:/

Quote:

What you're calling the "server" is apparently sending data continuously, and what you're calling the "client" is apparently reading the accumulated data once every 20 milliseconds. Is that the intent?

Normally, I'd expect the client to send a packet of data either on a fixed schedule or whenever the data is available, and the server would wait for data to appear before reading it and processing it immediately.
That is the intent, yes. On the LV program, I was following a simple tutorial to write the string; do you have any tips on how I could accomplish what you've described?

Quote:

TCP is a stream protocol and guarantees that things will be received in the correct order, but they may be packetized differently then you expect. You can learn more by searching for nagle algorithm.

Why are you sending data with no delay in LabVIEW, but reading data every 20ms? You'll probably fill up the TCP/IP buffers fairly quickly.
I'm not sure I completely understand. Are you saying that, because I'm using LV to write and C# to read, there's a discrepancy in the packet order? And I didn't really pay attention to it, I was following a tutorial :ahh:. Would it just be a ms timer in the loop?

Quote:

The code you have is extracting data from rData formatted as a string, where rData is the number of characters read from the socket stream. The actual data read from the stream is stored in info, which you aren't currently using
Oh, dangit. Careless mistake, haha. Fixed!


Do you guys think the problem is on the LV side or the C# side?

RyanCahoon 20-11-2013 09:36

Re: TCP problems in C#
 
Quote:

Originally Posted by Invictus3593 (Post 1303678)
Oh, dangit. Careless mistake, haha. Fixed!

Did that fix the problem? What's it outputting now? That modification will completely change the results you get

Also, how were you getting "a b c" - the code you had should have only given you numbers since you were just processing the number of bytes read. Were a b c placeholders? It might be helpful if you could give us some concrete examples

Alan Anderson 20-11-2013 09:37

Re: TCP problems in C#
 
Quote:

Originally Posted by Invictus3593 (Post 1303678)
Do you guys think the problem is on the LV side or the C# side?

It's on both sides. You need to throttle the sending side so that it doesn't overwhelm the network, and you need to change the receiving side so that it's always ready to receive data without introducing an artificial delay.

Since your application involves a fixed amount of data for each communication, I don't think the stream nature of TCP is helping you any. I suggest that you should be using UDP instead. That lends itself to a very simple structure where your C code can listen for a UDP packet and process the whole thing at once when it arrives.

Joe Ross 20-11-2013 12:39

Re: TCP problems in C#
 
Quote:

Originally Posted by Invictus3593 (Post 1303678)
I'm not sure I completely understand. Are you saying that, because I'm using LV to write and C# to read, there's a discrepancy in the packet order? And I didn't really pay attention to it, I was following a tutorial :ahh:.

I'm saying that the fundamental way that TCP operates makes what you want to do hard, no matter what is doing the sending and what is doing the receiving.

I agree with Alan that UDP is a better choice if all you want to do is blindly read a packet of data.

Invictus3593 20-11-2013 14:14

Re: TCP problems in C#
 
Quote:

Also, how were you getting "a b c" - the code you had should have only given you numbers since you were just processing the number of bytes read. Were a b c placeholders? It might be helpful if you could give us some concrete examples
I have not had the chance to test it yet, just fix the code, I will post the results after applying this test a little bit later. Originally, it did give me that specific string, but yes, those were placeholders so as to test the program before I actually inputted any real data. The real data will contain "a- encoder x-axis, b- encoder y-axis, and c- gyro angle" and the string that is read is then split up into the three parts and treated as three separate decimals.

Quote:

Since your application involves a fixed amount of data for each communication, I don't think the stream nature of TCP is helping you any. I suggest that you should be using UDP instead. That lends itself to a very simple structure where your C code can listen for a UDP packet and process the whole thing at once when it arrives.
Quote:

I agree with Alan that UDP is a better choice if all you want to do is blindly read a packet of data.
How would I go about reading from UDP if not from a stream? Would UDP affect the rate of the data sent? Is the syntax in C# any different? What do I need to keep in mind or be careful of when using UDP?

Sorry for all the questions in a row but I would like to know as much about this as possible so that when try it out, I can troubleshoot.

EDIT: One more thought; would using Network Tables help here? Maybe just getting the string from the LV Dashboard?

If you guys have any extra tips or resources I can check out about the two different protocols, PM me because I'm still learning!


All times are GMT -5. The time now is 03:03.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi