如何断开我的简单 tcp 服务器中的连接?

How do I drop the connection in my simple tcp server?

我用 tcp 举了一个非常简单的 rust 服务器示例。

use std::net::{Shutdown,TcpListener, TcpStream};
use std::thread;
use std::io::{Read,Write,Error};

fn handle_client(mut stream: TcpStream)-> Result<(), Error> {
    println!("incoming connection from: {}", stream.peer_addr()?);
    let mut buf = [0;512];
    loop {
        let bytes_read = stream.read(&mut buf)?;
        if bytes_read == 0 {return Ok(())}
        let tmp = format!("{}", String::from_utf8_lossy(&buf).trim());
        eprintln!("getting {}",tmp);
        stream.write(&buf[..bytes_read])?;
    }
}



fn main() {
    
    
    let listener = TcpListener::bind("0.0.0.0:8888").expect("Could not bind");
    for stream in listener.incoming() {
        match stream {
            Err(e)=> {eprintln!("failed: {}", e)}
            Ok(stream) => {
                thread::spawn(move || {
                    handle_client(stream).unwrap_or_else(|error| eprintln!("{:?}", error));
                });
            }
        } 
    }
}

它基本上接受输入,将其吐回客户端,然后打印到它自己的终端。

我希望能够结束此连接。结束连接应该取决于某些事情,但现在我只想尝试关闭它。

我尝试查看文档,然后尝试添加 shutdown 方法 现在,我想将一些流作为输入,对其进行处理,然后关闭频道

所以我尝试这样做:

fn main() {
    
    
    let listener = TcpListener::bind("0.0.0.0:8888").expect("Could not bind");
    for stream in listener.incoming() {
        match stream {
            Err(e)=> {eprintln!("failed: {}", e)}
            Ok(stream) => {
                
                thread::spawn(move || {
                    handle_client(stream).unwrap_or_else(|error| eprintln!("{:?}", error));
                });
                stream.shutdown(Shutdown::Both).expect("shutdown call failed");
                
            }
        } 
        
    }
}

但这会导致 "stream" 成为移动值的问题。

那么如何在接收到输入并对其进行处理后立即关闭频道?

(我还是想用循环保留这个结构,因为我其实想接收很多消息,然后根据输入关闭)

您可以尝试克隆流并将该流克隆传递给您生成的函数。然后,您可以在处理完客户端后在生成的函数中调用关闭。

这样,您的原始 stream 变量将保持不变,您可以拥有您想要的行为。

您遇到此问题的原因是生成的函数由于 move 关键字而移动它捕获的所有内容。

    fn main() {
    
    
    let listener = TcpListener::bind("0.0.0.0:8888").expect("Could not bind");
    for stream in listener.incoming() {
        let stream_clone = stream.clone();

        match stream {
            Err(e)=> {eprintln!("failed: {}", e)}
            Ok(stream) => {
                
                thread::spawn(move || {
                    handle_client(stream_clone).unwrap_or_else(|error| eprintln!("{:?}", error));
                 stream_clone.shutdown(Shutdown::Both).expect("shutdown call failed");
                });
            }
        }
    }
}

此外,您需要将句柄客户端的签名更改为 fn handle_client(stream: &mut TcpStream)-> Result<(), Error> 所以它也不会移动克隆的流变量,而是作为可变变量钻入。