0

Currently I have been working on a program that receives data from the server using TcpClient. My problem is that whenever I read the stream until I can my client stops working, It just freezes. I would like to keep a continous connection to the server, but after my while function ran twice, the third loop doesn't execute read, and never returns anything.

As this answer states that I'm correct

How can I break or return this while loop, or somehow bypass the reading block?

using (NetworkStream stream = client.GetStream())
{
    byte[] data = new byte[2048];
    using (MemoryStream ms = new MemoryStream())
    {

        int numBytesRead;
        while ((numBytesRead = stream.Read(data, 0, data.Length)) > 0)
        {
            ms.Write(data, 0, numBytesRead);
        }
        return ms.ToArray();
    }
}
Community
  • 1
  • 1
DreTaX
  • 760
  • 2
  • 9
  • 22
  • I can't tell from your code and description whether there's really a problem with the `Read` call, but assuming for the moment that it's simply taking a while to get the next batch of data, the only way to keep your GUI responsive during such a long read is by doing your networking on a separate thread. – adv12 Dec 31 '15 at 17:05
  • Actually, I'll qualify my above comment: you could also use `BeginRead`/`EndRead`. – adv12 Dec 31 '15 at 17:10
  • I really did test It, the server sends a byte of length 1654, and then the while reads It two times: 1460 and then 194 which is 1654. But when the 3rd loop runs and It would check if the data is 0, the loop just stucks there, and never launches anymore, just waiting for more data. – DreTaX Dec 31 '15 at 17:25
  • You while loop is bad. TCP can send datagrams with zero bytes. You must test for an end of data which can be any (or combination) of the following : 1) Ascii : Terminating character like '\n'. 2) Ascii or Binary : Add byte count to beginning of message and then read until all bytes are received. 3) Ascii or Binary : Fixed length message. Each type message has a known length. – jdweng Dec 31 '15 at 18:08
  • You should do `while (client.Connected && (numBytesRead = stream.Read(data, 0, data.Length)) > 0)` – metadings Dec 31 '15 at 18:13
  • This loop will not end until the server disconnects. Opposite of what you want. You'll have to write smarter code so the receiver knows when it has received all the data it needs. Send the length first so it knows and can simply count-off the bytes and not ask for too much. – Hans Passant Dec 31 '15 at 18:14
  • I see. I will check what would happen if i send the length first. It's annoying because I would like a persistent connection. – DreTaX Jan 01 '16 at 10:56
  • [Sending this way worked as a solution.](http://stackoverflow.com/questions/34503063/unable-to-decode-certificate-at-client-new-x509certificate2) – DreTaX Jan 01 '16 at 12:31

1 Answers1

-1

I will do my best to give you some hints. If you don't want the UI to be frozen, you should either put this code on a separate thread, or run it as an asynchronous task, as Wouter commented. In my opinion this would be the better approach if you neither know how many bytes you are expecting to receive, nor when they are coming to you. As you said, if you want to have this task running for a long time a thread would be a good solution.

Nevertheless, if possible, you should be concerned about two things: your TcpClient ReadTimeout property and the expected length you are passing through the third param of stream.Read(). This means that you'll be blocked for X milliseconds until you received the quantity you want. I worked a lot on transactional server, where data packages transferred between those networks came prefixed with the length of the package. If this is your case I recommend to read the prefix first, then calculate the quantity of bytes left to be read, and then perform the last read operation.

Hope this helps, this is my first answer.

Cindy Meister
  • 25,071
  • 21
  • 34
  • 43
  • The problem is that the read stucks on, while I already received the data. I will try to check the readtimeout. – DreTaX Dec 31 '15 at 17:35
  • How can you be sure you have received data if you are stuck on the Read() call? I'm sorry I did not understand your question at first glance. – Hernan Zbucki Dec 31 '15 at 21:29
  • "I really did test It, the server sends a byte of length 1654, and then the while reads It two times: 1460 and then 194 which is 1654. But when the 3rd loop runs and It would check if the data is 0, the loop just stucks there, and never launches anymore, just waiting for more data" The server says that the length is also 1654 – DreTaX Jan 01 '16 at 10:54