views:

545

answers:

3

Hi all, I utilize TcpClient class to implement a telnet connection. What I don't know is how to determine the end of response. It seems that once DataAvailable property is true, I read the data from Stream and DataAvailable is then temporarily set to false while buffer is being filled with another chunk of data but I think is all read and go away. How do I ensure that all response was read?

You might advise me how to change the code snippet below to make this work correctly. It works correctly when I step through the code because there is plenty of time for the whole response to be retrieved. Appreciate your help.

if (this.Stream.DataAvailable)
{
    readBuffer = new Byte[this.Client.ReceiveBufferSize];
    do
    {
        // read data
        bytes = this.Stream.Read(readBuffer, 0, readBuffer.Length);
        Thread.Sleep(10);
        responseData = String.Concat(responseData, System.Text.Encoding.ASCII.GetString(readBuffer, 0, bytes));

       } while (this.Stream.DataAvailable);

       allDataRead = true;
       break;
}
+2  A: 

With TCP connections for applications like Telnet there is no such concept as the end of the transmission. You'll often find telnet clients that send each key press one at a time as the user enters them and it's up to the server to decide when to take action, normally when it gets a line feed. Other clients may buffer up a few client key presses and send them all at once.

By the looks of your app you should be looking for line feeds to indicate the end of a transmission.

do    
{      
     bytes = this.Stream.Read(readBuffer, 0, readBuffer.Length);             
     responseData = String.Concat(responseData, System.Text.Encoding.ASCII.GetString (readBuffer, 0, bytes));       
} while (this.Stream.DataAvailable && !responseData.Contains("\n"));
sipwiz
A: 

I don't think it's a good idea to use DataAvailable for this purpose. The end of your response is whatever your protocol says it is.

It's better to use blocking calls like Read to read your stuff, and use whatever protocol you've established to determine to read more, and how much. It might be that not all data you want is returned, because Read doesn't return when all your data is read, but when some data is read, so you need to check on how much was read.

If your protocol is Telnet, you'll likely want to respond to every single byte received, as with a terminal you want to echo it or process commands or what not.

DataAvailable is perhaps suited to check if a Read would block when called (it will return with whatever is in the buffer) but it makes your loop less straightforward.

Dave Van den Eynde
A: 

Is this an actual telnet connection, i.e. are you connecting to a telnet server or by 'telnet' do you really mean 'TCP/IP socket'?

First determine whether the server drops the connection when the transmission is complete. If so, you can simply read until the end of the stream. Otherwise, if not, you are going to have to use a cue in the data to determine whether the read is complete. Different protocols work in different ways in this regard so if you could enlighten us to the protocol we may be able to give a more direct answer. Approaches generally fall into two camps: including a count of bytes/characters at the beginning of the response (the receiver simply reads that many bytes/characters) or else using a marker to delimit the end of the response (the receiver reads until receiving the delimiter).

Paul Ruane
It is a connection to telnet server using tcp/ip socket and port 23. The server does not terminate connection. The first part of the telnet session is authentication when the server asks for first username and then password. I will check the delimiter and let you know later. Thank you.
David
Assuming the telnet server is a console session upon a Unix/BSD/Windows/etc. server, then you can use the command prompt text as your delimiter.
Paul Ruane