سؤال

I am working on a project where I should run commands on Unix servers and get the full output of those commands. For this purpose, I am using Minimaslistic Telnet Library from code project (http://www.codeproject.com/Articles/19071/Quick-tool-A-minimalistic-Telnet-library). For now, everything works fine excepting the output, because I want to read it all, not just a portion of it. I can have commands that may take long time. Here is the read output method in the Minimaslistic Telnet Library :

public string Read()
{
    if (!tcpSocket.Connected) return null;
    StringBuilder sb=new StringBuilder();
    do
    {
        ParseTelnet(sb);
        System.Threading.Thread.Sleep(TimeOutMs);
    } while (tcpSocket.Available > 0);
    return sb.ToString();
}


void ParseTelnet(StringBuilder sb)
{
    while (tcpSocket.Available > 0)
    {
        int input = tcpSocket.GetStream().ReadByte();
        switch (input)
        {
            case -1 :
                break;
            case (int)Verbs.IAC:
                // interpret as command
                int inputverb = tcpSocket.GetStream().ReadByte();
                if (inputverb == -1) break;
                switch (inputverb)
                {
                    case (int)Verbs.IAC: 
                        //literal IAC = 255 escaped, so append char 255 to string
                        sb.Append(inputverb);
                        break;
                    case (int)Verbs.DO: 
                    case (int)Verbs.DONT:
                    case (int)Verbs.WILL:
                    case (int)Verbs.WONT:
                        // reply to all commands with "WONT", unless it is SGA (suppres go ahead)
                        int inputoption = tcpSocket.GetStream().ReadByte();
                        if (inputoption == -1) break;
                        tcpSocket.GetStream().WriteByte((byte)Verbs.IAC);
                        if (inputoption == (int)Options.SGA )
                            tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WILL:(byte)Verbs.DO); 
                        else
                            tcpSocket.GetStream().WriteByte(inputverb == (int)Verbs.DO ? (byte)Verbs.WONT : (byte)Verbs.DONT); 
                        tcpSocket.GetStream().WriteByte((byte)inputoption);
                        break;
                    default:
                        break;
                }
                break;
            default:
                sb.Append( (char)input );
                break;
        }
    }
}

This code sample reads output, but asynchronously, I need it to wait for output before quitting. Is there any idea about changing the code to meet my requirements? Thank you!

هل كانت مفيدة؟

المحلول

I agree with Joachim, calling the read in a loop and parsing for the end out the output is the best approach. Unfortunately for me, my output didn't have a standardize ending for each command I executed. Instead, I used the read timeout of the stream to approximate the end of the output (I realize this isn't perfect). I set a higher initial timeout to allow the data to start flowing, and then lowered the timeout to find the end of the output. It looks something like this:

static string ReadFromStream(int initialTimeout, int subsequentTimeout)
    {
        // Initialize output
        string output = null;

        try
        {
            // Set initial read timeout -- This is needed because occasionally
            // it takes a while before data starts flowing
            stream.ReadTimeout = initialTimeout;

            while (stream.CanRead)
            {
                // Read bytes in from stream
                readBuffer = new byte[tcpClient.ReceiveBufferSize];
                stream.Read(readBuffer, 0, tcpClient.ReceiveBufferSize);

                // Convert the bytes to string and save to output
                output = string.Format("{0}{1}", output, Encoding.ASCII.GetString(readBuffer).Trim());

                // Set subsequent read timeout
                stream.ReadTimeout = subsequentTimeout;
            }
        }
        // Since we don't know when the output will end, we wait for, and catch the timeout
        catch (IOException) { }

        // Return output
        return output;
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top