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

如何阻止Telnet客户端回显?Rust+Tokio TCP聊天服务器问题

解决MacOS Telnet连接Tokio TCP聊天服务器时的回显问题

核心原因

MacOS自带的Telnet默认使用「过时行模式」,客户端会默认回显输入内容。你之前尝试的IAC WONT ECHO方向搞反了——Telnet选项协商的逻辑是:

  • IAC WILL ECHO:服务器告知客户端「我来负责回显,你关闭自身回显」
  • IAC WONT ECHO:服务器告知客户端「我不负责回显,你自己处理」

发送错误的命令才会导致无效或报错。

具体修改步骤

基于Tokio官方chat示例,需要做两处修改:

1. 连接建立后发送正确的Telnet回显控制命令

在处理客户端连接的process函数开头,先向Socket发送IAC WILL ECHO序列,告知客户端关闭自身回显:

use tokio::io::{AsyncReadExt, AsyncWriteExt};

// 定义Telnet常量
const IAC: u8 = 255;
const WILL: u8 = 251;
const ECHO: u8 = 1;

async fn process(mut socket: tokio::net::TcpStream) -> Result<(), Box<dyn std::error::Error>> {
    // 首先发送Telnet回显控制命令
    socket.write_all(&[IAC, WILL, ECHO]).await?;
    
    // 原示例的后续代码...
    let mut buf = [0; 1024];
    loop {
        let n = socket.read(&mut buf).await?;
        if n == 0 {
            return Ok(());
        }
        // ...
    }
}

2. 过滤客户端发来的Telnet协商命令

客户端收到服务器的WILL ECHO后,会回复IAC DO ECHO确认,这些字节会被当成聊天内容读取,导致乱码或报错。需要在读取后过滤掉Telnet命令序列:

// 新增过滤函数
fn filter_telnet_commands(input: &[u8]) -> Vec<u8> {
    let mut output = Vec::new();
    let mut iter = input.iter().peekable();
    
    while let Some(&byte) = iter.next() {
        if byte == IAC {
            // 跳过IAC后的命令字节和选项字节(共2个)
            iter.next();
            iter.next();
        } else {
            output.push(byte);
        }
    }
    output
}

// 在读取数据后应用过滤
async fn process(mut socket: tokio::net::TcpStream) -> Result<(), Box<dyn std::error::Error>> {
    socket.write_all(&[IAC, WILL, ECHO]).await?;
    
    let mut buf = [0; 1024];
    loop {
        let n = socket.read(&mut buf).await?;
        if n == 0 {
            return Ok(());
        }
        
        // 过滤Telnet命令,只保留实际聊天内容
        let filtered_data = filter_telnet_commands(&buf[0..n]);
        if filtered_data.is_empty() {
            continue;
        }
        
        // 后续使用filtered_data代替原buf内容
        let msg = String::from_utf8_lossy(&filtered_data);
        // 原示例中的广播逻辑...
    }
}

效果验证

修改后重新启动服务器,用Telnet连接:

telnet localhost 6142

此时输入内容不会被客户端回显,只有当你按下回车发送后,服务器广播的消息(包括你自己的输入)会显示出来,同时保持了行模式的输入方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 06:32:17