为什么从 Unix 套接字读取时使用 netcat 发送 ^D 不会触发 EOF?

gor*_*ral 5 unix sockets rust

我正在尝试编写一个从 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
    }
}
Run Code Online (Sandbox Code Playgroud)

游乐场

在客户端我使用ncnc -U socket。我发送一些数据并以^DEOF 结尾。文档read_to_string说:

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

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

观察到的行为:服务器无法识别 EOF 已发送并阻塞。仅当客户端断开连接时,服务器才会打印消息并panic显示损坏的管道。

She*_*ter 5

\n

我发送一些数据并^D以 EOF 结尾

\n
\n\n

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

\n\n
\n

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

\n\n \n
\n\n\n\n
\n

ctrl+d 在 netcat 的标准输入上发送 EOF:netcat 注意到了 EOF。它将不再通过套接字发送任何数据。但是,如果服务器有更多数据要发送,它会继续运行并从套接字读取。

\n\n \n
\n\n

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

\n\n

您也许可以使用适合您的版本的-q或选项:-wnc

\n\n
\n

假设发送EOF后连接将保持空闲状态,您可以使用-w timeout选项,它的作用timeout等于零

\n\n \n
\n\n

您也可以尝试非交互式:

\n\n
$ echo \'hello\' | nc -U socket\nhello\n
Run Code Online (Sandbox Code Playgroud)\n\n

也可以看看:

\n\n\n

  • 这是我能想到的最糟糕的答案 - 我的 Rust 代码很好,但我花了半天时间试图修复它。 (3认同)
  • 当我这样称呼它时它起作用了:“nc -q 0 -U /tmp/socket”。 (2认同)

non*_*lar 5

我有类似的问题。尝试一下nc -N旗帜。

当输入达到 时,此标志会导致nc发送 TCP 套接字的 shutdown(2) EOF

在旧版本的 Ubuntu 上(在 14.04 上验证),它的表现就像-N总是通过(并且nc不支持-N)。

在较新的版本(在 Ubuntu 20.04 上验证)上,仅在-N设置标志时才表现出此行为。