【发布时间】:2014-06-26 23:34:17
【问题描述】:
这听起来很傻,但由于某种原因,这段代码似乎跳过了阅读。或者,也许它发展得太快了?我正在尝试从服务器获取 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**
【问题讨论】:
-
尝试执行
var response = tc.Read();之类的操作,然后在其上设置断点以帮助找出问题出在哪里。 -
好的,第一次通过它确实包含:“220 server-10.tower-555.messagelabs.com ESMTP\r\n”。当它第二次通过时,它包含一个空字符串。它似乎仍然停留在服务器响应的第一行。
-
你的错误处理很奇怪。如果出现错误,您什么也不做。这几乎是不合适的。
-
您不能那样使用“可用”。研究,它做了什么以及为什么它几乎总是一个错误。
-
有货吗?你是在说我的 try catch 异常块吗?我试图捕捉并查看它,这样我就可以看到出了什么问题。