根据此来源:C#使用TcpClient实现telnet功能_rr白开水的博客-CSDN博客_c#实现telnet
此链接为转载,但是我找不着原来的了。
在这代码基础上进行更改
先来看看页面
1. 点击连接进行数据连接
2.中间文本框是显示服务端那边传过来的字符,可自己输入端口信息,只要把组件名绑定就好
wpf代码,可以不和我这个一样,自己爱怎么摆怎么摆,主意命名就行:
<Window x:Class="MinimalisticTelnet.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Telnet" Height="332" Width="397.75">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="111*"/>
<ColumnDefinition Width="86*"/>
<ColumnDefinition Width="170*"/>
<ColumnDefinition Width="24*"/>
</Grid.ColumnDefinitions>
<TextBox HorizontalAlignment="Left" Height="23" Margin="10.284,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Grid.Column="1" Grid.ColumnSpan="2"/>
<TextBox HorizontalAlignment="Left" Height="24" Margin="10.284,41,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Grid.Column="1" Grid.ColumnSpan="2"/>
<TextBlock HorizontalAlignment="Left" Margin="10,11,0,0" TextWrapping="Wrap" Text="主机名" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,42,0,0" TextWrapping="Wrap" Text="端口" VerticalAlignment="Top"/>
<TextBox x:Name="TBhostname" Height="23" Margin="10.284,10,40.5,0" TextWrapping="Wrap" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"/>
<TextBox HorizontalAlignment="Left" Height="24" Margin="10.284,41,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" Grid.Column="1" Grid.ColumnSpan="2"/>
<TextBlock HorizontalAlignment="Left" Margin="10,99,0,0" TextWrapping="Wrap" Text="密码" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,70,0,0" TextWrapping="Wrap" Text="用户名" VerticalAlignment="Top"/>
<TextBox x:Name="TBusername" Height="24" Margin="10.284,70,40.5,0" TextWrapping="Wrap" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"/>
<TextBox x:Name="TBpassword" Height="24" Margin="10.284,99,40.5,0" TextWrapping="Wrap" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"/>
<TextBox x:Name="TBport" Height="24" Margin="10.284,41,40.5,0" TextWrapping="Wrap" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"/>
<Button x:Name="TBConnect" Content="连接" HorizontalAlignment="Left" Margin="135.284,56,0,0" VerticalAlignment="Top" Width="50" Click="TBConnect_Click" Grid.Column="2" RenderTransformOrigin="1.221,0.447" Height="29" Grid.ColumnSpan="2"/>
<Button x:Name="Btncommand" Content="命令" HorizontalAlignment="Left" Margin="141.284,0,0,10" Width="44" Click="TBConnect_Click" Grid.Column="2" Height="23" VerticalAlignment="Bottom" Grid.ColumnSpan="2"/>
<TextBox x:Name="TBcommand" Margin="10,0,0,10" TextWrapping="Wrap" Grid.ColumnSpan="3" HorizontalAlignment="Left" Width="315" Height="23" VerticalAlignment="Bottom"/>
<ListBox x:Name="TBListBox" Margin="10,128,10.716,40" SelectionChanged="TBwait1_SelectionChanged" FontWeight="Bold" FontSize="16" Grid.ColumnSpan="4" BorderThickness="0">
<TextBlock x:Name="TBwait" TextWrapping="Wrap" Text="TextBlock"/>
</ListBox>
</Grid>
</Window>
两个按钮,几个文本框,几个文本。
所有需要在C#代码里引用的我都做了命名前边加TB统一,例:TBhostname,TBport。
C#代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Net.Sockets;
namespace MinimalisticTelnet
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TBwait.Visibility = Visibility.Collapsed;
TBcommand.Visibility = Visibility.Collapsed;
Btncommand.Visibility = Visibility.Collapsed;
}
TcpClient tcpSocket;
private void TBConnect_Click(object sender, RoutedEventArgs e)
{
//获取当前点击的Button文本
string btn = System.Convert.ToString((sender as Button).Content);
if (btn == "连接")
{
//在端口上创建与主机名配对的新 Telnet 连接
//远程连接ll
tcpSocket = new TcpClient(TBhostname.Text, TBport.Text);
//本地连接(下回做一个本地的服务端,搭配使用)
//tcpSocket = new TcpClient("localhost", TBport.Text);
//使用用户“root”登录,密码“rootpassword”,使用100ms的超时,
//并显示服务器输出
string s = Login(TBusername.Text, TBpassword.Text, 100);
TBwait.Text = s;
TBwait.Visibility = Visibility.Visible;
InitializeComponent();
Console.Write(s);
#region 如果是本地连接就不需这些,直接注释即可
// 服务器输出应以“#”,否则连接失败
//s.TrimEnd() 服务器返回的数据
string prompt = s.TrimEnd();
prompt = s.Substring(prompt.Length - 1, 1);
if (prompt != "#")
throw new Exception("连接失败");
prompt = "";
#endregion
TBcommand.Visibility = Visibility.Visible;
Btncommand.Visibility = Visibility.Visible;
}
if (btn == "命令")
{
if (btn == "命令")
{
WriteLine(TBcommand.Text);
string s = Read();
TBwait.Text = s;
TBcommand.Text = "";
Console.Write(s + "\n");
}
}
Console.WriteLine("******DISCONNECTED******");
Console.ReadLine();
}
int TimeOutMs = 1 * 1000;
public string Login(string Username, string Password, int LoginTimeOutMs)
{
int oldTimeOutMs = TimeOutMs;
TimeOutMs = LoginTimeOutMs;
//接收服务器输出数据
string s = Read();
Console.Write(s+"\n");
#region 登录(如果是本地链接,不需要登录,可以把这段注释了)
if (!s.TrimEnd().EndsWith(":"))
throw new Exception("连接失败:无登录提示");
//输入登录账号
WriteLine(Username);
s += Read();
Console.Write(s + "\n");
if (!s.TrimEnd().EndsWith(":"))
throw new Exception("连接失败:无密码提示");
//输入登录密码
WriteLine(Password);
s += Read();
#endregion
Console.Write(s + "\n");
TimeOutMs = oldTimeOutMs;
return s;
}
public void DisConnect()
{
if (tcpSocket != null)
{
if (tcpSocket.Connected)
{
tcpSocket.Client.Disconnect(true);
}
}
}
public void WriteLine(string cmd)
{
Write(cmd + "\r\n");
}
public void Write(string cmd)
{
if (!tcpSocket.Connected) return;
//转换成中文编码GB2312
byte[] buf = System.Text.ASCIIEncoding.ASCII.GetBytes(cmd.Replace("\0xFF", "\0xFF\0xFF"));
//GetStream 返回一个可用来发送和接收数据的 NetworkStream
tcpSocket.GetStream().Write(buf, 0, buf.Length);
}
//服务器输出
//tcpSocket.Connected是否连接的上
public string Read()
{
//未连接就返回null
if (!tcpSocket.Connected) return null;
StringBuilder sb = new StringBuilder();
do
{
//解析远程登录
ParseTelnet(sb);
System.Threading.Thread.Sleep(TimeOutMs);
} while (tcpSocket.Available > 0);
return ConvertToGB2312(sb.ToString());
}
public bool IsConnected
{
get { return tcpSocket.Connected; }
}
//解析远程登录
void ParseTelnet(StringBuilder sb)
{
//tcpSocket.Available 获取已经从网络接收且可供读取的数据量。
while (tcpSocket.Available > 0)
{
//NetworkStream 异步读取 为网络访问提供数据的基础流。
//返回用于发送和接收数据的 NetworkStream
int input = tcpSocket.GetStream().ReadByte();
switch (input)
{
case -1:
break;
case (int)Verbs.IAC:
// 解释为命令
int inputverb = tcpSocket.GetStream().ReadByte();
if (inputverb == -1) break;
switch (inputverb)
{
case (int)Verbs.IAC:
//文本 IAC = 255 转义,因此将字符 255 附加到字符串
sb.Append(inputverb);
break;
case (int)Verbs.DO:
case (int)Verbs.DONT:
case (int)Verbs.WILL:
case (int)Verbs.WONT:
// 用“WONT”回复所有命令,除非它是 SGA(支持继续)
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;
}
}
}
//格式更改
private string ConvertToGB2312(string str_origin)
{
char[] chars = str_origin.ToCharArray();
byte[] bytes = new byte[chars.Length];
for (int i = 0; i < chars.Length; i++)
{
int c = (int)chars[i];
bytes[i] = (byte)c;
}
Encoding Encoding_GB2312 = Encoding.GetEncoding("GB2312");
string str_converted = Encoding_GB2312.GetString(bytes);
return str_converted;
}
private void TBwait1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
enum Verbs
{
WILL = 251,
WONT = 252,
DO = 253,
DONT = 254,
IAC = 255
}
enum Options
{
RD = 1,
SGA = 3
}
}
已经找不着最开始哪出来的,但是转载的找到了一个: