You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Linux通过Telnet发送Ctrl-C后为何停止接收数据?

问题分析与解决

问题现象

你编写的C# TCP回显程序,功能是读取字节并返回十六进制文本表示:

using System.Net;
using System.Net.Sockets;
using System.Text;

var listener = new TcpListener(IPAddress.Any, 5050);
listener.Start();

var client = listener.AcceptTcpClient();
var stream = client.GetStream();
int b;
while ((b = stream.ReadByte()) != -1) {
    var str = $"{(byte)b:x2} ";
    Console.Write(str);
    stream.Write(Encoding.ASCII.GetBytes(str));
}
  • 用Windows原生telnet连接时,输入内容(包括Ctrl-C以03发送)都能正常回显十六进制。
  • 用WSL2 Ubuntu或MSYS2的telnet连接时,按下Ctrl-C后:
    1. 程序控制台输出ff f4 ff fd 06
    2. 后续输入的内容仅在程序控制台显示,telnet客户端收不到回显数据

原因

WSL2/MSYS2的telnet客户端默认启用了Telnet协议选项协商,而Windows原生telnet默认是raw模式(不进行协商)。按下Ctrl-C时,WSL的telnet会发送Telnet协议的中断协商序列:

  • FF(IAC,Interpret As Command):标识后续字节为Telnet命令
  • F4(IP,Interrupt Process):请求中断远程进程
  • FF FD 06:DO 06,请求启用TIMING MARK选项

你的程序直接把这些协商字节当成普通数据处理并回显,但telnet客户端发送协商序列后会等待服务器的响应(比如WONT或WILL),如果没收到预期响应,客户端会进入“等待协商确认”状态,不再处理后续回显数据。

解决方案

方案1:让WSL/MSYS2的telnet使用raw模式

连接时添加-r参数,强制telnet以raw模式运行,不发送Telnet协商序列,Ctrl-C会直接发送03字节:

telnet -r localhost 5050

这样就能和Windows原生telnet表现一致。

方案2:修改C#程序处理Telnet协商字节

如果需要兼容带协商的telnet客户端,可在程序中识别并处理Telnet命令序列,避免把协商字节当成普通数据回显,同时回复客户端的协商请求。示例修改如下:

using System.Net;
using System.Net.Sockets;
using System.Text;

var listener = new TcpListener(IPAddress.Any, 5050);
listener.Start();

var client = listener.AcceptTcpClient();
var stream = client.GetStream();
int b;
while ((b = stream.ReadByte()) != -1) {
    // 处理Telnet协议命令
    if (b == 0xFF) { // 识别IAC命令起始字节
        var cmd = stream.ReadByte();
        if (cmd == -1) break;
        // 处理DO/DONT/WILL/WONT类选项协商命令,统一回复WONT拒绝
        if (cmd is 0xFB or 0xFC or 0xFD or 0xFE) {
            var opt = stream.ReadByte();
            if (opt == -1) break;
            // 发送WONT响应,告知客户端拒绝该选项
            stream.WriteByte(0xFF);
            stream.WriteByte(0xFC); // WONT命令码
            stream.WriteByte((byte)opt);
        }
        // 跳过IP等中断类命令,不回显
        continue;
    }

    // 处理普通数据,回显十六进制格式
    var str = $"{(byte)b:x2} ";
    Console.Write(str);
    stream.Write(Encoding.ASCII.GetBytes(str));
}

该修改会识别Telnet的IAC命令,对选项协商回复WONT拒绝,跳过中断命令,让telnet客户端完成协商流程,后续输入内容即可正常回显。

内容的提问来源于stack exchange,提问作者Alexey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 01:57:54