Telnet 连接未将制表符写入文件

Ren*_*nma 5 c# unix

我有一个 C# WPF 应用程序,它建立 Telnet 连接以将一些内容从 Windows 系统写入 Linux 系统上的文件。假设我有一些这样的文字。

这是一段文本 \r\n 后跟一个新行。

代码的大致流程如下:

string ipAddress = "11.11.11.11";
int port = 66;
TelnetConnection tc = new TelnetConnection(ipAddress, port);
string s = tc.Login("root", "password", 100);
string prompt = s.TrimEnd();
if (prompt != "$" && prompt != "#"){
    throw new Exception("Connection failed");
}
tc.WriteLine("echo $'Here is a bit\tof text \r\n Followed by a new line.' >> MyFile.txt");
Run Code Online (Sandbox Code Playgroud)

这是我使用的 TelnetConnection 类:\

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

enum Options
{
    SGA = 3
}

class TelnetConnection
{
    TcpClient tcpSocket;

    int TimeOutMs = 10;

    public TelnetConnection(string Hostname, int Port)
    {
        tcpSocket = new TcpClient(Hostname, Port);

    }

    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);
        System.Threading.Thread.Sleep(1000);
    }

    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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我去检查文件时,它是这样写入的

这是一段文本,
后面跟着一个新行。

因此制表符甚至没有被读取,但新行是出于某种原因。有任何想法吗?

小智 0

@Johannes Krackowizer 给出了正确的答案,但解释缺少一个细节:“TelnetConnection”不是文件。您正在做的就是向远程计算机打字。@Greg M 也提到了这一点。

当您发送\t字符串时,您正在发送一个文字<tab>字符。另一端的计算机正在尝试为您完成输入文件名,因为这就是您点击 时发生的情况<tab>。如果您想取回选项卡,您需要发送 a\和 a t。您t可以直接发送,但\需要发送,\\因为\如您所知,它是转义字符。所以发送:

"echo $'Here is a bit\\tof text \r\n Followed by a new line.' >> MyFile.txt"
Run Code Online (Sandbox Code Playgroud)

注意bit\\tof带有两个反斜杠的。那么为什么\r\n有效呢?因为它是<Enter>and ,并且您正在键入的<Ctrl>+<Enter>字符串是在单引号内键入的。当您使用单引号时,您可以点击并继续输入,直到完成并以最后的 结尾。<Enter>'

正如其他人提到的,printf通常是首选:

"printf $'Here is a bit\\tof text \r\n Followed by a new line.\n' >> MyFile.txt"
Run Code Online (Sandbox Code Playgroud)

接下来,在您的代码中,反斜杠也应该被转义,因此您可能也需要转义这些字符:

tc.WriteLine("printf $'Here is a bit\\\\tof text \\r\\n Followed by a new line.\\n' >> MyFile.txt");
Run Code Online (Sandbox Code Playgroud)