这听起来很愚蠢,但由于某些原因,这段代码似乎跳过了阅读。或者它可能太快了?我正试图从服务器获得一个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**
答案 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);
我希望它可以帮到你!
告诉我它是否适合你。