V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bli22ard
V2EX  ›  Rust

rust TcpStream 为什么设计读写一体

  •  
  •   bli22ard · 1 天前 · 487 次点击
    fn main(){
        let mut ts1=TcpStream::connect(("127.0.0.1", 6666)).unwrap();
        //读写全都在一起
        ts1.write("hello".as_bytes()).unwrap();
        let mut buf=[0;1024];
        ts1.read(&mut buf).unwrap();
        //这样设计,在一些情况不方便
    
        //1 两个 TcpStream 需要全双工拷贝
        let mut ts2=TcpStream::connect(("127.0.0.1", 6667)).unwrap();
        //这里不得不进行 clone
        let mut ts11=ts1.try_clone().unwrap();
        let mut ts22=ts2.try_clone().unwrap();
        thread::spawn(move||{
           std::io::copy(&mut ts1,&mut ts2).unwrap();
        });
    
        thread::spawn(move||{
            std::io::copy(&mut ts22,&mut ts11).unwrap();
        });
        // 以下两种情况以开发一个 http server 为场景
        //2 当需要将 TcpStream 使用 BufReader  和  BufWriter 封装构造一个结构体给上层使用
        
        struct Req{
            br:BufReader<TcpStream>,
            bw:BufWriter<TcpStream>,
        }
        //3 如果不进行 buf 封装,底层处理也不能使用 buf 进行读取,因为 buf 读取可能会读取超过底层处理的数据的长度,这样底层
        // 只能使用非 buf 方式进行读取,效率就比较低下
        struct Req1{
            ts:TcpStream
        }
        
        
    }
    
    

    目前我能想到的 TcpStream 读写一体,是为了 drop 时候自动关闭 tcp 连接,但是这样确实带来了诸多不便。 同样 BufReader 、BufWriter 在 new 的时候传&TcpStream ,不能生成一个具有所有权的 br 、bw ,会依赖&TcpStream 。TcpStream 为什么不提供一个 getWriter 和 getReader 两个分离的函数呢?

    7 条回复    2024-09-23 21:50:19 +08:00
    nagisaushio
        1
    nagisaushio  
       1 天前 via Android
    可以用 BufReader<Arc<TcpStream>>
    SingeeKing
        2
    SingeeKing  
       1 天前 via iPhone
    BufReader/BufWriter+ cloned TcpStream 有什么问题吗?

    毕竟底层是一个 fd ,就算提供你想要的 get_reader 和 get_writer 底层肯定还是一个 clone ,和自己 clone 相比也没啥提升
    PTLin
        3
    PTLin  
       14 小时 41 分钟前
    你的想法也没什么问题。标准库没提供,只能手动 clone ,但是 tokio 提供了你想要的功能。
    https://docs.rs/tokio/latest/tokio/net/struct.TcpStream.html#method.split
    bli22ard
        5
    bli22ard  
    OP
       3 小时 51 分钟前
    @nagisaushio BufReader 是没问题,但是 BufWriter 我试了下不行。因为 BufWriter<W: ?Sized + Write> 而 Arc<TcpStream> 没有实现 Write 。arc 套 buf 看起来只能实现 Reader 不能实现 Writer 。
    bli22ard
        6
    bli22ard  
    OP
       3 小时 41 分钟前
    @SingeeKing 一些资料上说,TcpStream try_clone 采用底层操作系统的 dup (在 Unix 上)或 DuplicateHandle (在 Windows 上)来创建一个新的文件描述符,该描述符指向同一个底层套接字,这样会占用一个文件描述符。另外这样调用 try_clone 不够直观。
    bli22ard
        7
    bli22ard  
    OP
       3 小时 34 分钟前
    @PTLin
    @capric tokio 现在还没用, 不过这个 split 够优雅。 看来这个阻塞 io 下没有一个好的方式来处理这个分离的问题。不知道 tokio split 底层具体实现的原理的是什么
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1426 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 17:25 · PVG 01:25 · LAX 10:25 · JFK 13:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.