我正在用这个让自己疯狂,因为从文档来看它应该是无痛的:如何将字符串转换为 &[u8] 以便我可以通过 TCP 或 UDP 通过网络发送它? bytes!() 宏似乎只能直接处理文字。

这是 TCP 应用程序的框架,完全来自其他来源。现在它作为回声服务器工作。我遇到的绊脚石是弄清楚如何在终端上将 &[u8] 打印为字符串,或者如何将字符串从 io::stdin().read_line() 转换为 &[u8] 以通过网络以聊天方式发送。

这无法在 error: mismatched types: expected `&[u8]` but found `&str` (expected vector but found &str) 上编译:

fn run_tcp_test_server(listen_addr: SocketAddr) {
    let mut acceptor = TcpListener::bind(listen_addr).listen().unwrap();
    println("[ INFO ] listener is ready.");

    loop {
        let stream = Cell::new(acceptor.accept().unwrap());
        do spawn {
            println("[ INFO ] got a request.");

            let mut stream = stream.take();

            let mut my_read_buff = ~[0, ..1024];
            match stream.read(my_read_buff) {
                Some(n) => {
                    stream.write(my_read_buff.slice_to(n));
                },
                _ => ()
            }

            let out_msg = "Hello World\r\n";
            stream.write(out_msg);
        }
    }
}

我也不认为 let mut my_read_buff = ~[0, ..1024] 可能是正确的,这似乎是等待发生的 C 样式溢出,我认为 Rust 应该修复它。

我对此很困惑,我的理解是 &str&[u8] 并且我被类型系统绊倒了,但无法克服这一点。我试图在不安全的块中实现 std::str::raw 中的一些功能,但也没有运气。

最佳答案

&str&[u8] 具有相同的表示,但它有一个额外的不变式:内容总是有效的 UTF-8,因此它不是相同的类型,即你必须在它们之间明确地“转换”(有点类似于 u8i8具有相同的表示,但需要显式转换才能在适当的位置使用它们)。这个“转换”是用 .as_bytes() &str&[u8] 完成的, std::str::from_utf8 用于另一个方向(在 0.8 上,反向转换是 from_utf8_slice FWIW)。 &str&[u8] 转换非常非常便宜;对其进行优化实际上是零成本(另一个方向必须检查有效的 UTF-8,因此是 O(n)),并且关闭它们仍然是对具有非常少数量的函数的函数调用指示。

因此,您需要:

stream.write(out_msg.as_bytes());

(如果 out_msg 总是相同的消息,您实际上可以使用 b 前缀来获取编译时字节文字:
stream.write(b"Hello World\r\n")

)



不,向量和切片的长度存储在其中,因此 .read 调用知道允许填充多少空间,并且不会/不能写入超出它的末尾。

(FWIW,如果您的缓冲区始终是固定长度,您可以删除 ~ ,即 let mut my_read_buff = [0, ..1024]; ,因此 my_read_buf 将具有类型 [u8, .. 1024] ,即 1024 u8 的固定长度向量。这避免了堆分配。)

关于tcp - 访问 &str 作为 &[u8],我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20891327/

10-11 20:54