Telnet / TcpClient C#跳过代码而不是循环遍历

时间:2014-06-02 21:24:47

标签: c# loops telnet tcpclient

这听起来很愚蠢,但由于某些原因,这段代码似乎跳过了阅读。或者它可能太快了?我正试图从服务器获得一个telnet响应,我得到了第一线响应,但仅此而已。无论我放了多少readline()或者我尝试睡眠线程都没关系。我该怎么做才能从服务器上获得整个响应?我想我把问题缩小到退出。在示例程序中,如果您对出口进行硬编码,它会立即结束循环并且不显示任何内容。我试着睡觉了,但这似乎阻止了一切。

输出:

220 server-12.tower-558.messagelabs.com ESMTP

预期产出:

250-server-11.tower-555.messagelabs.com says EHLO to iphere
250-PIPELINING
250-8BITMIME
250-STARTTLS

我的代码:

 //Telnet Start
 IPHostEntry hostInfo = Dns.Resolve(list[j]);
 TelnetConnection tc = new TelnetConnection(hostInfo.AddressList[0].ToString(), 25);
 string prompt = "a";
 string consoleout = "";
 // while connected
 while (tc.IsConnected && prompt != "exit")
 {
 // display server output
 prompt = "ehlo a.com";
 tc.WriteLine(prompt);
 //I've tried adding a 2 or 5 second thread sleep here and I still get the same result.
 Console.Write(tc.Read());
 prompt = "exit";
 }
 //Telnet End

TelnetConnection类:

// minimalistic telnet implementation
// conceived by Tom Janssens on 2007/06/06  for codeproject
//
// http://www.corebvba.be



using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;

namespace MinimalisticTelnet
{
    enum Verbs {
        WILL = 251,
        WONT = 252,
        DO = 253,
        DONT = 254,
        IAC = 255
    }

    enum Options
    {
        SGA = 3
    }

    class TelnetConnection
    {
        TcpClient tcpSocket;

        int TimeOutMs = 100;

        public TelnetConnection(string Hostname, int Port)
        {
            try
            {
                tcpSocket = new TcpClient(Hostname, Port);
            }
            catch (SocketException e)
            {
                Console.Write(e);
            }

        }

        public string Login(string Username,string Password,int LoginTimeOutMs)
        {
            int oldTimeOutMs = TimeOutMs;
            TimeOutMs = LoginTimeOutMs;
            string s = Read();
            if (!s.TrimEnd().EndsWith(":"))
               throw new Exception("Failed to connect : no login prompt");
            WriteLine(Username);

            s += Read();
            if (!s.TrimEnd().EndsWith(":"))
                throw new Exception("Failed to connect : no password prompt");
            WriteLine(Password);

            s += Read();
            TimeOutMs = oldTimeOutMs;
            return s;
        }

        public void WriteLine(string cmd)
        {
            Write(cmd + "\n");
        }

        public void Write(string cmd)
        {
            if (!tcpSocket.Connected) return;
            byte[] buf = System.Text.ASCIIEncoding.ASCII.GetBytes(cmd.Replace("\0xFF","\0xFF\0xFF"));
            tcpSocket.GetStream().Write(buf, 0, buf.Length);
        }

        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();
        }

        public bool IsConnected
        {
            get { return tcpSocket.Connected; }
        }

        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;
                }
            }
        }
    }
}

更新

使用以下循环我能够让它工作一次,但只有当我确认j为2时它才会迭代j的计数。我的输出,预期输出和功能都在下面。

功能:

for (int j = 0; j < list.Count; j++)
{
//Telnet Start
Console.WriteLine("On round #" + j);
IPHostEntry hostInfo = Dns.Resolve(list[j]);
TelnetConnection tc = new TelnetConnection(hostInfo.AddressList[0].ToString(), 25);
string prompt = "a";
string consoleout = "";
// while connected
while (tc.IsConnected && prompt != "exit")
{
// display server output
Console.Write(tc.Read());

// send client input to server
prompt = "ehlo a.com";
tc.WriteLine(prompt);

// display server output
consoleout = tc.Read();
Console.Write(consoleout);

//send exit input to server
prompt = "exit";
tc.WriteLine(prompt);
Console.Write(tc.Read());
}
Console.WriteLine("**DISCONNECTED**");
//Telnet End
if (consoleout.IndexOf("STARTTLS")>-1)
{
if (j == 0)
{
if (list[j].Contains(domains[i]))
dataGridView1.Rows.Add(domains[i], list[j], "Y", numberemployees, "Y");
else
dataGridView1.Rows.Add(domains[i], list[j], "Y", numberemployees, "N");
}
else
{
if (list[j].Contains(domains[i]))
dataGridView1.Rows.Add(null, list[j], "Y", null, "Y");
else
dataGridView1.Rows.Add(null, list[j], "Y", null, "N");
}
}
else
{
if (j == 0)
{
if (list[j].Contains(domains[i]))
dataGridView1.Rows.Add(domains[i], list[j], "N", numberemployees, "Y");
else
dataGridView1.Rows.Add(domains[i], list[j], "N", numberemployees, "N");
}
else
{
if (list[j].Contains(domains[i]))
dataGridView1.Rows.Add(null, list[j], "N", null, "Y");
else
dataGridView1.Rows.Add(null, list[j], "N", null, "N");
}
}

}

输出:

On round #0
True220 server-6.tower-95.messagelabs.com ESMTP
250-server-6.tower-95.messagelabs.com
250-STARTTLS
250-PIPELINING
250 8BITMIME
502 unimplemented (#5.5.1)
**DISCONNECTED**
On round #1
True220 server-14.tower-558.messagelabs.com ESMTP
**DISCONNECTED**

预期产出:

On round #0
True220 server-6.tower-95.messagelabs.com ESMTP
250-server-6.tower-95.messagelabs.com
250-STARTTLS
250-PIPELINING
250 8BITMIME
502 unimplemented (#5.5.1)
**DISCONNECTED**
On round #1
True220 server-14.tower-558.messagelabs.com ESMTP
250-STARTTLS
250-PIPELINING
250 8BITMIME
**DISCONNECTED**

所以无论出于何种原因,它根本不会进行第二次循环。但它也开始依赖于服务器。有些服务器会回复一些信息,有些服务器会得到类似的信息,这样看起来就像什么都没发生一样。

On round #0
True220 SMTP Proxy Server Ready
**DISCONNECTED**
On round #1
True220 SMTP Proxy Server Ready
**DISCONNECTED**
On round #2
True220 SMTP Server Ready
**DISCONNECTED**
On round #3
True220 SMTP Server Ready
**DISCONNECTED**
On round #4
True220 SMTP Proxy Server Ready
**DISCONNECTED**
On round #5
True220 SMTP Proxy Server Ready
**DISCONNECTED**

2 个答案:

答案 0 :(得分:1)

凯尔,

看起来你需要打开套接字:

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

它没有打开,所以它正在返回。

<强> [UPDATE]

IPHostEntry hostInfo = Dns.Resolve(list[j]);评论之前尝试循环播放//Telnet Start

private const int PORT25 = 25; // I hate magic numbers

foreach (var item in list) {
  var hostInfo = Dns.Resolve(item);
  Console.WriteLine(hostInfo);
  foreach (var address in hostInfo.AddressList) {
    var tc = new TelnetConnection(address, PORT25);
    Console.WriteLine("{0} TelnetConnection Connected: {1}", address, tc.IsConnected);
  }
}

[更新2]

这很难调试,不知道你要连接的是什么以及还有什么。

那就是说,让我们尝试以下方法:

在您的班级MinimalisticTelnet中,添加以下方法:

public void Close() {
    if (tcpSocket != null) {
        tcpSocket.Close();
    }
}

我在其他任何地方都看不到它,这可能会在您下次尝试第二次连接时造成一些问题。

现在,在您的测试代码中,在 while循环之后添加新的一行代码:

while (tc.IsConnected && prompt != "exit") {
    // display server output
    Console.Write(tc.Read());

    // send client input to server
    prompt = "ehlo a.com";
    tc.WriteLine(prompt);

    // display server output
    consoleout = tc.Read();
    Console.Write(consoleout);

    //send exit input to server
    prompt = "exit";
    tc.WriteLine(prompt);
    Console.Write(tc.Read());
}
tc.Close();
Console.WriteLine("**DISCONNECTED**");

运气好的话,你的第二次连接失败的原因是因为你仍然有一个开放的连接。

答案 1 :(得分:0)

我解决了一个类似的问题,添加3次读取,然后8秒超时,最后再次读取并显示在我的RICHTEXBOX中:


string r1 = conexion.Read();

string r2 = conexion.Read();

string r3 = conexion.Read();

System.Threading.Thread.Sleep(8000);

richtextbox.AppendText(r1 + r2 + r3);


我希望它可以帮到你!

告诉我它是否适合你。