IRC 服务器不响应 Rust IRC 客户端识别请求

IRC server doesn't respond to Rust IRC Client identify requests

我正在使用标准库中的 TcpStream 开发 IRC 机器人。

我能够阅读输入的所有行,但 IRC 服务器似乎没有响应我的身份请求。我以为我发送请求的时间太早了,所以我尝试在发送 IDENT 之前先睡觉,但这不起作用。我使用 BufReaderBufWriter 和直接在流上调用 readwrite 来编写,但无济于事。

use std::net::TcpStream;
use std::io::{BufReader, BufWriter, BufRead, Write, Read};
use std::{thread, time};
struct Rusty {
    name: String,
    stream: TcpStream,
    reader: BufReader<TcpStream>,
    writer: BufWriter<TcpStream>,
}
impl Rusty {
    fn new(name: &str, address: &str) -> Rusty {
        let stream = TcpStream::connect(address).expect("Couldn't connect to server");
        let reader = BufReader::new(stream.try_clone().unwrap());
        let writer = BufWriter::new(stream.try_clone().unwrap());
        Rusty {
            name: String::from(name),
            reader: reader,
            writer: writer,
            stream: stream,
        }
    }
    fn write_line(&mut self, string: String) {
        let line = format!("{}\r\n", string);
        &self.writer.write(line.as_bytes());
    }
    fn identify(&mut self) {
        let nick = &self.name.clone();
        self.write_line(format!("USER {} {} {} : {}", nick, nick, nick, nick));
        self.write_line(format!("NICK {}", nick));
    }
    fn read_lines(&mut self) {
        let mut line = String::new();
        loop {
            self.reader.read_line(&mut line);
            println!("{}", line);
        }
    }
}
fn main() {
    let mut bot = Rusty::new("rustyrusty", "irc.rizon.net:6667");
    thread::sleep_ms(5000);
    bot.identify();
    bot.read_lines();
}

阅读我们在编程时使用的组件的文档非常重要。例如,BufWriter 的文档指出(强调我的):

Wraps a writer and buffers its output.

It can be excessively inefficient to work directly with something that implements Write. For example, every call to write on TcpStream results in a system call. A BufWriter keeps an in-memory buffer of data and writes it to an underlying writer in large, infrequent batches.

The buffer will be written out when the writer is dropped.

换句话说,缓冲 reader 或写入器的 全部目的 readwrite 请求 不要与底层流有一对一的映射。

这意味着当您调用 write 时,您只是将 写入缓冲区 。如果需要确保将字节写入基础流,还需要调用 flush


此外,您应该:

  1. 处理 readwriteflush 可能引起的错误。
  2. 重新熟悉每个函数的作用。例如,readwrite 不保证它们会按照您的要求读取或写入尽可能多的数据。他们可能会执行部分读取或写入,由您来处理。这就是为什么有像 read_to_endwrite_all.
  3. 这样的辅助方法的原因
  4. 清除您正在阅读的String。否则每次循环都会重复输出。
  5. 使用 write! 而不是构建一个立即被丢弃的字符串。
fn write_line(&mut self, string: &str) {
    write!(self.writer, "{}\r\n", string).unwrap();
    self.writer.flush().unwrap();
}

通过这些更改,我能够从服务器获得 PING 消息。