精华内容
下载资源
问答
  • 介绍 SocketAddr定义如下: pub enum SocketAddr { V4(SocketAddrV4), V6(SocketAddrV6), } 使用示例 SocketAddr中提供了一些方法,使用如下: use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, ... let mut s...

    介绍

    SocketAddr定义如下:

    pub enum SocketAddr {
        V4(SocketAddrV4),
        V6(SocketAddrV6),
    }
    

    使用示例

    SocketAddr中提供了一些方法,使用如下:

    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
    
    fn main() {
        let mut socket = 
            SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
            assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
        let socket_v6 = 
            SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080);
        
    
        //返回IP
        assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
    
        //设置IP:修改socketAddr对应的Ip
        socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
        assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
    
        //返回端口
        assert_eq!(socket.port(), 8080);
    
        // 设置端口:修改socketAddr对应的端口
        socket.set_port(1025);
        assert_eq!(socket.port(), 1025);
    
    
        // 判断是否为ipv4
        assert_eq!(socket.is_ipv4(), true);
        assert_eq!(socket_v6.is_ipv4(), false);
    
        // 判断是否为ipv6
        assert_eq!(socket.is_ipv6(), false);
        assert_eq!(socket_v6.is_ipv6(), true);
    }
    
    展开全文
  • rust 网络编程
  • 近日学习Substrate的开发入门,之前没有接触过Rust编程,今天跟着视频做个小项目练练手 项目目标: 编写一个Tcp server端与一个Tcp client端,客户端中输入内容后,服务端可以返回相应的输入内容 项目实现: 服务端...

    近日学习Substrate的开发入门,之前没有接触过Rust编程,今天跟着视频做个小项目练练手


    项目目标:

    编写一个Tcp server端与一个Tcp client端,客户端中输入内容后,服务端可以返回相应的输入内容

    项目实现:

    服务端的实现:

    //
    //@author Bayek
    //@dev server用于监听
    //
    use std::net::{TcpListener, TcpStream}; 
    use std::thread;
    //std::thread库的引入,对输入的每一个流创建一个线程
    use std::time;
    use std::io::{self, Read, Write};
    //引入io库,为了处理错误
    
    fn handle_client(mut stream: TcpStream) -> io::Result<()> {
        //该函数用来处理client(就是这个流),流的格式或者说他的类型就是TcpStream
        let mut buf = [0; 512];
        //创建一个叫buf的数组,内容为0,长度为512
        loop {
            //该循环表示server端永久提供服务,因为默认服务器为永不关闭的
            let bytes_read = stream.read(&mut buf)?;
            //从流里面读内容,读到buf中
            if bytes_read == 0 {
                return Ok(());
                //如果读到的为空(即0),则说明已经结束了
            }
            stream.write(&buf[..bytes_read])?;
            //否则把它写回去
            thread::sleep(time::Duration::from_secs(1));
            //调用sleep函数实现服务的间隔,间隔1s
        }
    }
    
    fn main() -> io::Result<()> {
        let listener = TcpListener::bind("127.0.0.1:8080")?;
        //定义一个listener,bind函数里面填写的是监听的的ip与端口号,?是一种简写,等价于except,unwrap
        let mut thread_vec: Vec<thread::JoinHandle<()>> = Vec::new();
        //创建一个容器,用来放线程的句柄
    
        for stream in listener.incoming() {
            let stream = stream.expect("failed");
            //转换一下stream流,出现问题,提示“失败”,没有问题,继续下面的操作
            let handle = thread::spawn(move || {
                handle_client(stream).unwrap_or_else(|error| eprintln!("{:?}", error));
            });
            //对输入的每一个流来创建一个线程,利用必包进行一个处理
            thread_vec.push(handle);
            //把handle加到容器里面
        }
    
        for handle in thread_vec {
            //此循环为了等待线程的结束
            handle.join().unwrap();
            //等待结束的具体实现
        }
        Ok(())
    }
    
    

    客户端的实现:

    //
    //@author Bayek
    //@dev server端进行监听,在client端发起链接
    //
    use std::io::{self, prelude::*, BufReader, Write};
    use std::net::TcpStream;
    use std::str;
    
    fn main() -> io::Result<()> {
        let mut stream = TcpStream::connect("127.0.0.1:8080")?;
        //创建变量stream,直接连接sever端
        for _ in 0..10 {
            let mut input = String::new();
            //定义一个String类型的输入
            io::stdin().read_line(&mut input).expect("Failed to read!");
            //从标准输入读入一行,读入input里面,如果有问题的话,提示“读取失败”
            stream.write(input.as_bytes()).expect("Failed to write!");
            //把input读取的内容,转换成bytes后,写到stream流里面去,如果写入失败,提示“写入失败”
    
            let mut reader = BufReader::new(&stream);
            //从stream流创建一个读,目的是要从我们的server端读,
            let mut buffer: Vec<u8> = Vec::new();
            //用Vector创建一个buffer变量 
            reader.read_until(b'\n', &mut buffer).expect("Failed to read into buffer");
            //一直读到换行为止(b'\n'中的b表示字节),读到buffer里面
            println!("read from server: {}", str::from_utf8(&buffer).unwrap());
            //把读取到buffer中的内容打印出来
            println!("");
            //再来一个换行,美化输出
        }
        Ok(())
    }
    

    运行结果:

    server端运行 cargo run 编译运行程序:
    在这里插入图片描述

    client端同样运行 cargo run 编译运行程序,可以看到来自服务端返回的消息,服务端读取了来自客户端输入的内容,并返回了读取内容
    在这里插入图片描述


    项目视频来自B站UP:程序员令狐壹冲
    01Rust网络编程,实现TCP server:https://www.bilibili.com/video/BV1b54y1X7my
    02Rust网络编程,Tcp client端:https://www.bilibili.com/video/BV1b54y1X7my?p=2
    我不是UP本人,我不是UP本人,我不是UP本人,此博客为个人的学习笔记(手动狗头)

    展开全文
  • 根据官方的测试结果,在性能方面Rust网络编程框架比JAVA和GO要好得多 但是我意外的看到像Rust中Tokio这样优秀的高并发网络编程框架在中文技术社区却没有个完整的教程,但是在周末鸡娃的时候,我意外发现小朋友对于...

    今天我们继续高并发的话题,传统的云计算技术,本质上都是基于虚拟机的,云平台可以将一些性能强劲的物理服务器,拆分成若干个虚拟机,提供给用户使用,但在互联网发展到今天,虚拟机还是太重了。即使是飞天集群,新增部署虚拟机的时间也是以分钟来计的。但是对于互联网用户来讲20秒的等等就是就会千万50%以上的用户流失,不能忍受的煎熬,因此无GC更不依赖JVM的Rust,无论在冷启速度还是在内存消耗上都比JAVA和GO更具优势,而且相比C语言Rust的生产效率也更高,很多储如从函数式语言借鉴而来的Future机制都非常先进,根据官方的测试结果,在性能方面Rust的网络编程框架比JAVA和GO要好得多

    但是我意外的看到像Rust中Tokio这样优秀的高并发网络编程框架在中文技术社区却没有个完整的教程,但是在周末鸡娃的时候,我意外发现小朋友对于Future、async/await机制理解起来却很容易 ,因此笔者决定将这段时间与小孩一起探索Tokio的心得向大家分享一下,做为基础入门的学习材料。

    初识Tokio

    Tokio是基于Rust开发的异地网络编程框架,用于执行异步代码的多线程运行时。通过Future、async/await等机制,开发者可以让代码产生极高生产力的同时保持程序的性能基本与C语言一致,基于Tokio的开发在编写异步代码时,开发者不能使用Rust标准库提供的阻塞api,而必须使用由Tokio提供,镜像了Rust标准库的API。我们先来看一个Tokio的Helloworld程序

    1.首先创建项目

    cargo new my-tokio

    命令创建一个my-tokio的项目

    1. 修改Cargo.toml

    vi Cargo.toml

    在依赖处添加以下内容

    [dependencies]
    
    tokio = { version = "1", features = ["full"] }
    1. 修改源代码

    vi src/main.rs

    并将代码替换为以下内容

    async fn say_word() {
    
        println!("my tokio");
    
    }
    
    #[tokio::main]
    
    async fn main() {
    
        let op = say_word();
    
        println!("hello");
    
        op.await;
    
    }
    1. 编译并执行

    cargo build

    cargo run

    结果如下:    

    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
    
         Running `target/debug/my-tokio`
    
    hello
    
    my tokio

    这里我们先解释一下async和await的用法,我们看到async fn say_word()中,say_word()函数是被async关键词修饰的,那么也就是说这个函数在被调用时 let op = say_word();

    ,以上代码是被立即返回而没有被执行的,而这时op实际是一个Future,也就是一个现在为空,在未来才会产生的值(有关Future的机制我们接下来解释),而在调用op.await的时其实是在等到这个async异步操作执行完毕才返回,是一个阻塞操作,因此最终输出会是先打印hello,然后再打印my tokio

    程序 程序员如何理解更像自然语言的Future

        在以下这段代码中,网络连接socket、请求发送request、响应接收response三个对象全部都是future类型的,也就是在代码执行之后不会被执行也没有值仅有占位的意义,当未来执行后才会有值返回,and_then方法其实是在future对象执行成功后才会被调用的方法,比如read_to_end这行代码就是在request对象执行成功后,调用read_to_end方法对读取结果。

    use futures::Future;
    
    use tokio_core::reactor::Core;
    
    use tokio_core::net::TcpStream;fn main() {
    
        let mut core = Core::new().unwrap();
    
         let addr = "127.0.0.1:8080".to_socket_addrs().unwrap().next().unwrap();
    
         let socket = TcpStream::connect(&addr, &core.handle());
    
    
    
         let request = socket.and_then(|socket|{
    
             tokio_core::io::write_all(socket, "Hello World".as_bytes())
    
         });
    
         let response = request.and_then(|(socket, _)| {
    
             tokio_core::io::read_to_end(socket, Vec::new())
    
         });
    
    
    
         let (_, data) = core.run(response).unwrap();
    
         println!("{}", String::from_utf8_lossy(&data));
    
     }

    而想象一下如果是传统编程所采用的方式,需要在网络连接完成后调用请求发送的回调函数,然后再请求发送的响应处理方法中再注册接收请求的回调函数,复杂不说还容易出错。

    上面的代码就是建立Tcp连接,发送数据,最后取返回每个Future都是通过and_then建立关系,而future机制精髓之处在于,整个过程是通过core.run(response).unwrap();这行代码运行起来的,也就是说在Future的帮助下,程序员只需要关心最终的结果就可以了整个链条通过poll机制串联,从poll机制来看,这几个模块的传递机制如下:

    从建立网络连接开始的调用链交给计算机去帮你完成,不但省去了回调所带来的复杂性,最终的效率反而还会更高。

    poll模到底是什么意思?

    笔者看到不少博主在介绍Rust的Future等异步编程框架时都提到了Rust的Future采用poll模式,不过到底什么是poll模式却大多语焉不详其实poll做的本质工作就是监测链条上前续Future的执行状态。

    以上述情况为例,poll的方向是由response到request最后是socket,但是state和data的返回方向是完全返过来的,也就是说response通过poll来获取request的state,而request也同样通过poll来获取socket的state。

    笔者还是这样的观点,程序员群体之所以觉得future机制难以理解,其关键在于思维模式被计算机的各种回调机制给束缚住了,而忘记了最简单直接的方式。在解决这个问题之前我们先来问一个问题,假如让我们自己设计一个类似于tokio这样的异步Future管理器,应该如何入手?

    最直接也是最容易想到的方案就是事件循环,定期遍历整个事件队列,把状态是ready的事件通知给对应的处理程序,这也是我们常说的select方案;另外一种做法是在事件poll管理器中直接拿到处理程序的句柄,不再遍历整个事件队列,而是直接在中断处理响应中把通知发给对应处理进程,比如上述例子中实际是按照poll的链条传递的处理进程句柄的,这就是Poll模式。而基于poll设计的如tokio框架进行应用开发时,程序员根本不必关心整个消息传递,只需要用and_then、spawn等方法建立链条并让系统工作起来就可以了。

    而epoll(多路复用)是基于poll的另一种高并发机制,这种机制可以监视多个描述符,一旦某个描述符状态变为就绪,能够通知对应的handler进行后续操作。笔者在前文《这位创造了Github冠军项目的老男人,堪称10倍程序员本尊》中曾经介绍过Tdengine的定时器,其中就有这种多路复用的思想。由于操作系统timer的处理程序还不支持epoll的多路复用,因此每注册一个timer就必须要启动一个线程进行处理,资源浪费严重,因此Tdengine自己实现了一个多路复用的timer,可以做到一个线程同时处理多个timer,这些细节上的精巧设计也是Tdengine封神的原因之一。

    后记

    写到这突然发现tokio框架的介绍一篇文章根本就不可能完成,那么本文权当一个基础介绍,为入门tokio做准备,如果后面读者们再有强烈需求,我们再继续聊这个话题。

    展开全文
  • fn main() { protoc_rust_grpc::Codegen::new() .out_dir("src") .input("foobar.proto") .rust_protobuf(true) .run() .expect("protoc-rust-grpc"); } 编写Cargo.toml文件 在文件中添加如下内容: [dependencies]...

    演示说明

    本例子的功能为grpc客户端向服务端写入位置信息和读取位置信息,演示环境为ubuntu。

    准备工作

    安装protobuf编译器:

    apt install protobuf-compiler
    

    演示实例

    新建工程

    cargo new use_grpc --lib #记住这个名字use_grpc,因为在编写代码的时候要用
    

    新建proto文件

    在use_grpc目录下,创建foobar.proto文件,编写代码如下:

    syntax = "proto3";
    
    package foobar;
    
    service FooBarService {
       rpc record_cab_location(CabLocationRequest) returns (CabLocationResponse);
       rpc get_cabs(GetCabRequest) returns (GetCabResponse);
    }
    
    message CabLocationRequest {
       string name = 1;
       Location location = 2;
    }
    
    message CabLocationResponse {
       bool accepted = 1;
    }
    
    message GetCabRequest {
       Location location = 1;
    }
    
    message GetCabResponse {
       repeated Cab cabs = 1;
    }
    
    message Cab {
       string name = 1;
       Location location = 2;
    }
    
    message Location {
       float latitude = 1;
       float longitude = 2;
    }
    

    创建构建脚本

    在use_grpc目录下,创建build.rs文件,编辑如下:

    extern crate protoc_rust_grpc;
    
    fn main() {
        protoc_rust_grpc::Codegen::new()
        .out_dir("src")
        .input("foobar.proto")
        .rust_protobuf(true)
        .run()
        .expect("protoc-rust-grpc");
    }
    

    编写Cargo.toml文件

    在文件中添加如下内容:

    [dependencies]
    protobuf = "2"
    grpc = "0.7.1"
    grpc-protobuf = "0.7.1"
    futures = "0.3.*"
    tls-api = "0.3.*"
    
    [build-dependencies]
    protoc-rust-grpc = "0.7.1"
    
    [[bin]]
    name = "client"
    test = false
    
    [[bin]]
    name = "server"
    test = false
    

    编写源码

    编写lib.rs

    编写src目录下lib.rs,如下:

    pub mod foobar;
    pub mod foobar_grpc;
    

    编写服务端

    在src目录下创建bin目录,在bin目录中创建server.rs,编写如下:

    use std::thread;
    
    use use_grpc::foobar_grpc::*;//use_grpc为当前包的名字,如果名字不一样需要修改
    use use_grpc::foobar::*;//use_grpc为当前包的名字,如果名字不一样需要修改
    
    struct FooBarServer;
    
    impl FooBarService for FooBarServer {
        fn record_cab_location(&self, 
            _o: grpc::ServerHandlerContext, 
            req: grpc::ServerRequestSingle<CabLocationRequest>, 
            resp: grpc::ServerResponseUnarySink<CabLocationResponse>) 
            -> grpc::Result<()>
        {
            let mut r = CabLocationResponse::new();
    
            println!("Recorded cab {} at {}, {}", req.message.get_name(), req.message.get_location().latitude, req.message.get_location().longitude);
    
            r.set_accepted(true);
            resp.finish(r)
        }
    
        fn get_cabs(&self, 
            _o: grpc::ServerHandlerContext, 
            _req: grpc::ServerRequestSingle<GetCabRequest>, 
            resp: grpc::ServerResponseUnarySink<GetCabResponse>)
             -> ::grpc::Result<()>
        {
            let mut r = GetCabResponse::new();
    
            let mut location = Location::new();
            location.latitude = 40.7128;
            location.longitude = -74.0060;
    
            let mut one = Cab::new();
            one.set_name("Limo".to_owned());
            one.set_location(location.clone());
    
            let mut two = Cab::new();
            two.set_name("Merc".to_owned());
            two.set_location(location.clone());
    
            let vec = vec![one, two];
            let cabs = ::protobuf::RepeatedField::from_vec(vec);
    
            r.set_cabs(cabs);
    
            resp.finish(r)
        }
    }
    
    fn main() {
        let mut server = grpc::ServerBuilder::new_plain();
        server.http.set_port(9001);
        server.add_service(FooBarServiceServer::new_service_def(FooBarServer));
        // server.http.set_cpu_pool_threads(4);
        let _server = server.build().expect("Could not start server");
        loop {
            thread::park();
        }
    }
    

    编写客户端

    在src/bin目录下创建client.rs,编写如下:

    use use_grpc::foobar::*;//use_grpc为当前包的名字,如果名字不一样需要修改
    use use_grpc::foobar_grpc::*;//use_grpc为当前包的名字,如果名字不一样需要修改
    use futures::executor;
    
    use grpc::ClientStubExt;
    
    
    fn main() {
        let client = 
            FooBarServiceClient::new_plain("127.0.0.1", 
            9001, 
            Default::default())
            .unwrap();
    
        let mut req = CabLocationRequest::new();
        req.set_name("foo".to_string());
    
        let mut location = Location::new();
        location.latitude = 40.730610;
        location.longitude = -73.935242;
        req.set_location(location);
    
        let resp = client
            .record_cab_location(grpc::RequestOptions::new(), req)
            .join_metadata_result();
        let resp = executor::block_on(resp);
        match resp {
            Err(e) => panic!("{:?}", e),
            Ok((_, r, _)) => println!("{:?}", r),
        }
    
        let mut nearby_req = GetCabRequest::new();
        let mut location = Location::new();
        location.latitude = 40.730610;
        location.longitude = -73.935242;    
        nearby_req.set_location(location);
    
        let nearby_resp = client
            .get_cabs(grpc::RequestOptions::new(), nearby_req)
            .join_metadata_result();
        let nearby_resp = executor::block_on(nearby_resp);
        match nearby_resp {
            Err(e) => panic!("{:?}", e),
            Ok((_, cabs, _)) => println!("{:?}", cabs),
        }
    }
    

    编译

    cargo build//编译
    

    编译完成后的目录结构为:

    use_grpc
        |----- build.rs
        |----- Cargo.toml
        |----- foobar.proto
        |----- src
                |----- lib.rs
                |----- foobar_grpc.rs
                |----- foobar.rs
                |----- bin
                        |----- client.rs
                        |----- server.rs
    

    其中foobar_grpc.rs和foobar.rs为编译生成的文件。

    运行

    进入到target/Debug目录下。

    • 先运行服务端
      ./server
      
    • 运行客户端
      ./client
      
    展开全文
  • 本例子用Rust实现一个基于TCP的echo的服务端和客户端的程序,用Rust演示简单的网络程序。 服务端 服务端实现类似于我们之前写过的http服务端的实现。涉及到的知识点主要是std::io和std::net。 代码如下: use std::...
  • 我们在上文《小朋友也能听懂的Rust网络编程框架知识-Tokio基础篇》对于Tokio的基础知识进行了一下初步的介绍,本文就对于Tokio的用法及原理进行进一步的介绍与说明。 目前市面上绝大多数编程语言所编写的程序,执行...
  • libpnet为Rust提供一组跨平台的底层网络API。 依赖 [dependencies] pnet = "0.25.0" 源码示例 use pnet::datalink::Channel::Ethernet; use pnet::datalink::{self, NetworkInterface}; use pnet::packet::ethernet...
  • 介绍 gRPC是由google开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。 通过gRPC,客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,能够让用户更容易地创建分布式应用...
  • FTP协议介绍 FTP(File Transfer Protocol,文件传输协议)是 TCP/IP 协议组中的协议之一。其主要作用是在服务器和客户端之间实现文件的传输和共享。FTP协议运行在TCP连接上,保证了文件传输的可靠性。...
  • Rust网络编程:同步网络I/O

    千次阅读 2021-02-19 11:22:08
    这些通信规则被称为网络协议,设备彼此之间发送的消息被称为网络数据包。 为了分离各方面的关注度,例如可靠性、可发现性及封装性,这些协议被分成若干层,其中较高层协议堆叠在较低层协议之上。每个网络数据包由...
  • 本示例使用Rust编写一个FTP的客户端,在客户端中进行下载和上传的演示。 客户端 在Cargo.toml文件中添加: [dependencies] ftp = "3.0.1" 编写src/main.rs如下: use std::str; use std::io::Cursor; use ftp::...
  • 我们在上文《Rust网络编程框架-Tokio进阶》介绍了async/await和锁的基本用法,并完成了一个Server端的DEMO代码。本文继续来探讨这个话题。 客户端代码DEMO 上文中依靠telnet来触发服务端代码的执行,本文我们将...
  • } To and from Yaml serialized: --- workers: 100 ignore: false auth_server: auth.server.io deserialized: ServerConfig { workers: 100, ignore: false, auth_server: Some( "auth.server.io", ), } 网络例子 ...
  • 介绍 IpAddr定义如下: // IpAddr结构体定义: pub enum IpAddr { V4(Ipv4Addr), V6(Ipv6Addr), } 使用示例 IpAddr提供了一些方法,使用如下: use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};... ...
  • Rust学习网络编程TCP/IP基本原理Low-Level Academy是一个致力于使底层编程更容易的网站。目前只有第一章节的内容。Read More: https://lowlvl...
  • 本例子用Rust程序实现一个tftp_server,然后使用tftp客户端进行测试。 tftp服务端 新建工程: cargo new use_tftp 在Catgo.toml增加如下: [dependencies] tftp_server = "0.0.3" 编辑src/main.rs如下: use...
  • Rust版本:1.41.0 其它依赖安装准备: sudo apt-get install openssl sudo apt-get install libssl-dev sudo apt install pkg-config sudo apt install pkgconf 演示示例 编写Cargo.toml,添加如下: ...
  • TFTP介绍 TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。TFTP基于UDP,对应端口号为69. ...
  • 本例子用Rust实现一个基于UDP的服务端和客户端的程序。服务端收到字符串后,做一个逆序,然后返回。 知识点 udp主要用到net库中的UdpSocket。 源码 服务端 use std::net::UdpSocket; fn main() -> std::io...
  • ipnet ipnet主要提供一组IP CIDRs相关的API,可以用来进行相应的操作。 依赖 //Cargo.toml //----snip---- [dependencies] ipnet = "2.3.0" 源码示例 extern crate ipnet; use std::net::{Ipv4Addr, ...use ipne...
  • 使用SMTP,可实现相同网络处理进程之间的邮件传输,也可通过中继器或网关实现某处理进程与其它网络之间的邮件传输。 SMTP工作在两种情况下,一种是电子邮件从客户机传输到服务器,另外一种是从某个服务器传输到另外...
  • 此章节并不是只有Rust网络编程的内容,但是由于后续的例子有些依赖于此知识点,所以放在Rust网络编程系列中做简单介绍。参考资料主要是官方文档《Cargo之书》。 介绍 在实际的项目中,有些包需要编译第三方非Rust...
  • Rust进行网络编程 这是发布的“ 进行的代码库。 它包含从头到尾完成本书所必需的所有支持项目文件。 关于这本书 Rust级别很低,足以提供对内存的细粒度控制,同时通过编译时验证提供安全性。 这使其特别适合于编写...
  • 006 Rust 网络编程,mio 库介绍

    千次阅读 2020-05-04 08:06:25
    mio 标准库也缺乏对套接字和连接的细粒度控制,例如设置SO_REUSEADDR。mio库则提供了很多方法来解决这些问题。 依赖 [dependencies] mio = { version = "0.7.0", features = ["os-poll", "tcp"]} ...
  • 介绍 Trust-DNS是一个实现DNS协议和客户端功能的库。该库包含DNS记录序列化和通信的基本实现,通过它能够执行查询、更新和通知等操作。Trust-DNS Resolver是对应的DNS解析库,包括对应的IPv4和IPv6的一些实现。...
  • 用于Rust的Serde的自定义反序列化功能此板条箱提供定制的De / Serialization辅助功能,与Serde的with-annotat结合使用用于Rust的Serde的自定义De / Serialization辅助功能。 。 Serde在serde#553跟踪类似助手的心愿...
  • 深入浅出Rust异步编程之Tokio

    千次阅读 2020-02-17 09:49:51
    本文以tokio为例简单介绍Rust异步编程相关的一些知识。首先让我们看看为什么使用rust来进行异步编程。这里tokio官方给出了一个性能测试的对比,可以看到tokio是性能最好,实际...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,829
精华内容 2,331
关键字:

rust网络编程