【问题标题】:Why does sending ^D with netcat not trigger an EOF when reading from a Unix socket?为什么从 Unix 套接字读取时使用 netcat 发送 ^D 不会触发 EOF?
【发布时间】:2019-05-07 04:14:14
【问题描述】:

我正在尝试编写一个将从 Unix 套接字读取的服务器:

use std::io::prelude::*;
use std::os::unix::net::{UnixListener, UnixStream};

fn main() {
    let socket_name = "socket";

    let listener = match UnixListener::bind(&socket_name) {
        Err(err) => panic!("Failed to bind to socket: {}.", err),
        Ok(stream) => stream,
    };

    for mut stream in listener.incoming() {
        match stream {
            Ok(ref mut stream) => {
                let msg = read(stream);
                stream.write_all(msg.as_bytes()).expect("Echo");
            }
            Err(err) => panic!("Error occured when listening from the stream. {}", err),
        }
    }

    fn read(stream: &mut UnixStream) -> String {
        let mut s = String::new();
        stream.read_to_string(&mut s).unwrap();
        s
    }
}

(playground)

在客户端我使用nc:nc -U socket。我发送一些数据并以应该是 EOF 的 ^D 结束。 read_to_string 的文档说:

读取此源中 EOF 之前的所有字节,并将它们附加到 buf

预期行为: 在客户端发送 ^D 后,服务器以 echo 响应

观察到的行为: 服务器无法识别 EOF 已发送并阻止。只有当客户端断开连接时,服务器才会打印消息和带有断开管道的panics。

【问题讨论】:

    标签: sockets unix rust


    【解决方案1】:

    我发送一些数据并以 ^D 结束,这应该是一个 EOF

    对于nc 的输入。这并不意味着套接字本身已关闭:

    当 netcat 在其标准输入上遇到 EOF 时,它可能会或可能会 不关闭其 TCP 连接的发送部分,具体取决于哪个 它是 netcat 的版本。

    ctrl+d 在 netcat 的标准输入上发送 EOF:netcat 注意到了 EOF。它不会通过套接字发送更多数据。然而,它 继续运行并从套接字读取,以防服务器有 更多数据要发送。

    无论如何,我无法使用系统提供的nc 在 macOS 10.14.1 上重现您的问题。

    您也许可以为您的nc 版本使用-q-w 选项:

    假设发送 EOF 连接后将保持空闲,您可以使用 -w timeout 选项,该选项适用于 timeout 等于零

    你也可以尝试非交互:

    $ echo 'hello' | nc -U socket
    hello
    

    另见:

    【讨论】:

    • 这是我能想到的最糟糕的答案 - 我的 Rust 代码很好,但我花了半天时间试图修复它。
    • 当我这样称呼它时它起作用了:nc -q 0 -U /tmp/socket
    猜你喜欢
    • 2013-03-21
    • 2017-03-18
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2012-11-29
    • 2021-10-29
    相关资源
    最近更新 更多