3

The code below reads everything there is to read from tcp client stream, and on the next iteration it will just sit there on the Read() (i'm assuming waiting for data). How can I ensure it doesn't and just returns when there's nothing there to read? Do I have to set low timeout, and respond to an exception when it fails out? Or there's a better way?

TcpClient tcpclnt = new TcpClient();
tcpclnt.Connect(ip, port);

Stream stm = tcpclnt.GetStream();

stm.Write(cmdBuffer, 0, cmdBuffer.Length);

byte[] response = new Byte[2048];

MemoryStream ms = new MemoryStream();
byte[] buffer = new Byte[2048];
int length;
while ((length = stm.Read(buffer, 0, buffer.Length)) > 0)
    ms.Write(buffer, 0, length);

byte[] response = ms.ToArray();


tcpclnt.Close();
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
flamey
  • 2,311
  • 4
  • 33
  • 40

4 Answers4

1

TcpClient has two properties that I would play with.

  1. NoDelay Gets or sets a value that disables a delay when send or receive buffers are not full.
  2. ReceiveTimeout Gets or sets the amount of time a TcpClient will wait to receive data once a read operation is initiated
Khadaji
  • 2,147
  • 2
  • 17
  • 19
  • I would think the correct answer should be (2): http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.receivetimeout.aspx – Andrew Y Jul 21 '09 at 00:04
  • NoDelay only affects send buffers, and it does eventually send, after 5ms or so. https://en.wikipedia.org/wiki/Nagle's_algorithm – servermanfail Jun 01 '12 at 19:31
1

Maybe you should use multithreading. One thread should wait for data, another should process received data.

M. Jahedbozorgan
  • 6,914
  • 2
  • 46
  • 51
  • Viable solution but here's the scenario (it makes having a thread overkill for the scene..): imagine the POP3 protocol, you send a line, receive a line.. and a "." on its own line to signify end of message. But now imagine a different protocol, where server sends "Username:" and that's it--no CR/LF. StreamReader.ReadLine() will hang forever. Fine for POP3, but change 1 byte and taking a different schematical approach (not to mention LOC) sounds wrong to me. – servermanfail Jun 01 '12 at 19:35
0
var socket = new System.Net.Sockets.TcpClient();
            socket.NoDelay = true;
            socket.Connect(uri.Host, port);
            var ns = socket.GetStream();
            int timeout = 500; //ms
            DateTime lastReceived = DateTime.Now;
            string buffer = "";
            while (true)
            {
                if (ns.DataAvailable)
                {
                    var b = ns.ReadByte();
                    buffer += b + ", "; //customise this line yourself
                    lastReceived = DateTime.Now;
                    continue;
                }
                if (lastReceived.AddMilliseconds(timeout) < DateTime.Now) break;
                System.Threading.Thread.Sleep(timeout / 5);
            }
servermanfail
  • 2,532
  • 20
  • 21
0

Does the server have "Keep Connections Alive" on ?

I have had servers which will send you a stream of empty bytes as long as you request them.

Turning "Keep Connections Alive" stopped it doing this.

Mark Broadhurst
  • 2,675
  • 23
  • 45
  • tnx 4 reply. I can't change anything at the server. also, if I do set tcp client timeout to 1 sec it will timeout and throw the exception. so, no, i'm not getting empty bytes. – flamey May 07 '09 at 16:20
  • Have you tried adding break points or a counter to see if its hanging or just stuck in a loop ? – Mark Broadhurst May 07 '09 at 16:41
  • its not stuck in a loop. its stuck on Read(). if I replace a loop with two consecutive stm.Read(buffer, 0, buffer.Length) lines, the first time it receives 20 bytes and goes over to the next line, and that's where it sits. or alternatively, if I make buffer size 10, it will iterate twice to get those 20 bytes, and then sit at the next, third, iteration. – flamey May 07 '09 at 16:53