views:

451

answers:

2

From reading a few questions and answers here, it seems that a telnet stream never really closes. Using DataAvailable() will not return.

I've inherited some code that took a very very long time to complete and we thought it was the telnet server that was the problem. However, there is a byte[32757] which the code tries to store the response of the telnet server in.

Something like the following:

Byte byteArray[] = new Byte[32757];
TcpClient sock = new TcpClient();
sock.GetStream().read(byteArray, 0 byteArray.length);

If there isn't 32757 bytes or more, I'm assuming this code waits until enough empty packets are sent to make up the size of the byte array. Is this correct?

Is there a way to check if the telnet server has finished sending everything it wants to? There is no visible terminating char or string in each 'page' of the telnet session.

I was thinking a way to correct this code is to read a few bytes at a time, add that to a string, check the string for a terminating character or set of chars and return if found. Otherwise, read more bytes, add that to the string, and check again.

Suggestions?

+3  A: 

No, Stream.Read doesn't generally wait until it's read everything, and it's even less likely to for a network stream. It will read whatever data is available, or block until there's some data available, but that's all.

There's no real concept of the server "finishing" sending what it's going to send, unless either:

  • a) it tells you in advance how much it's going to send
  • b) it indicates when it's finished with some sort of termination data
  • c) it closes the connection

You may want to use a timer of some sort to achieve an effect of "keep reading until one of the reads takes more than 5 seconds". Note that the read would still be happening though - you'd just pick that time to update the UI (or whatever). It's quite a tricky topic, and you really need to be very clear in your own mind (and docs!) what you want to do, and which thread's going to handle what.

An alternative is to set a read timeout on the TcpClient, but I don't have experience of that. You'd probably just need to use TcpClient.ReceiveTimeout and then handle the resulting IOException appropriately when reading, but I don't have any advice to offer on it.

Jon Skeet
+4  A: 

In addition to Jon Skeets explanation a little tip:

since telnet is a text (line) based protocol, reading in byte[] means you'll have to re-assemble the text. You'll be better off with a TextReader:

System.IO.TextReader reader = new System.IO.StreamReader(
           sock.GetStream(), Encoding.ASCII);
string line;
while ((line = reader.ReadLine()) != null)  ...;

I'm guessing here that telnet uses ASCII.

Henk Holterman