当前位置:首页 > CN2资讯 > 正文内容

windows2019 自建rustdesk服务器

2天前CN2资讯


Rust


文章目录

  • Rust
  • 开发环境搭建
  • 在线模式
  • 离线模式
  • 引入自定义第三方库
  • 通用编程概念
  • Hello
  • 注释
  • 印屏
  • Display
  • 变量
  • 变量可变性
  • 不可变变量与常量
  • 变量冻结
  • 延迟绑定
  • 变量隐藏
  • 数据类型
  • 基本数据类型
  • 类型别名
  • 简单类型转换
  • From和into
  • String
  • Array
  • Tuple
  • Struct
  • Tuple Struct
  • 函数与表达式
  • 条件语句
  • 循环语句
  • 所有权
  • 内存位置
  • 引用位置
  • 字符串位置
  • 默认分配位置
  • 所有权转移
  • 引用与借用
  • 可变引用
  • 悬垂引用(Dangling References)
  • 裸指针
  • 切片(Slice)
  • 引用生命周期
  • &、ref、*
  • 自动解引用
  • 模式匹配
  • 匹配数字
  • 枚举类型
  • C Like
  • Rust Style
  • Option
  • if let
  • panic!
  • Result
  • 错误判断
  • 错误类型
  • 简化Result展开
  • 传播错误
  • 泛型与特性
  • 实现(Implementation)
  • 特性(Trait)
  • 特性组合
  • 运算符重载
  • 特性实现重叠
  • 泛型(Generic)
  • 模拟重载(Overload)
  • 多态
  • Collection
  • Vector
  • HashMap
  • IO
  • 命令行
  • 命令行参数
  • 命令行输入
  • 读取环境变量
  • 读写文件
  • 文件写入
  • 文件读取
  • 函数式编程
  • Closure
  • Lambda表达式
  • 所有权捕获
  • Iterator
  • 消费迭代器
  • 自定义迭代器
  • 智能指针
  • 指针类型
  • Box
  • Rc
  • Cell&RefCell
  • Weak
  • 递归类型
  • Deref
  • Drop
  • Module
  • 单文件
  • 多文件
  • Macro
  • unsafe
  • Thread
  • join
  • channel
  • Mutex & Arc
  • Sync & Send
  • Socket
  • Tcp
  • UdpBroadcast


开发环境搭建

  • :Windows下确保已完成MinGW-w64(推荐使用MingW-W64-builds)的安装;

在线模式

  • :下载Rustup安装程序;
  • :打开命令窗口输入以下命令:
@REM SET CARGO_HOME= @REM SET RUSTUP_HOME= SET RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static SET RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup .\rustup-init.exe
  • :提示缺少Microsoft C++ build tools,回车继续;
If you will be targeting the GNU ABI or otherwise know what you are doing then it is fine to continue installation without the build tools, but otherwise, install the C++ build tools before proceeding. Continue? (Y/n) Y
  • :自定义安装信息:
1) Proceed with installation (default) 2) Customize installation 3) Cancel installation >2
  • :配置default host triple,其它选择直接回车使用默认:
Default host triple? x86_64-pc-windows-gnu

最终配置如下:

default host triple: x86_64-pc-windows-gnu default toolchain: stable profile: default modify PATH variable: yes
  • :继续安装等待安装完成:
1) Proceed with installation (default) 2) Customize installation 3) Cancel installation >1

离线模式

  • :下载Standalone installers;
  • x86_64-windows: x86_64-pc-windows-gnu
  • x86_64-linux: x86_64-unknown-linux-gnu
  • aarch: aarch64-unknown-linux-gnu
  • :下载Source Code
  • :下载rustfmt用于自动格式化代码;

修改配置

# Linux vim ~/.cargo/config.tomlREM Windows notepad %USERPROFILE%\.cargo\config.toml
引入自定义第三方库

Cargo.toml

[dependencies] libname = { path = "..." }

通用编程概念

Hello

fn main() { println!("hello world!"); }

注释

// Line comments which go to the end of the line. /* Block comments which go to the closing delimiter. */// Doc comments which are parsed into HTML library documentation: /// Generate library docs for the following item. //! Generate library docs for the enclosing item.

印屏

// 一行 print!("line\n"); println!("line"); // 输出{} println!("{{}}"); // 输出\ println!("\\");

说明

{}

Display trait

{:?}

Debug trait

{:e}

LowerExp trait

{:E}

UpperExp trait

{:o}

Octal trait

{:p}

Pointer trait

{:b}

Binary trait

{:x}

LowerHex trait

{:X}

UpperHex trait

#[allow(dead_code)] #[derive(Debug)] // This make it printable by {:?}. struct Student { id: i64, name: String, age: i32, gender: bool, } let student = Student { id: 9955845621, name: String::from("Peter"), age: 0x1a, gender: false, }; println!("Hello {}!", ); println!("{0}'s name is {0}.", ); println!("{yourname}'s name is {yourname}.", yourname = ); println!("{0}'s id is {1}.", , student.id); println!("{0}'s id is {1:e}.", , student.id); println!("{0}'s id is {1:E}.", , student.id); println!("{0} is {1} years old.", , student.age); println!("{0} is 0b{1:b} years old.", , student.age); println!("{0} is 0o{1:o} years old.", , student.age); println!("{0} is 0x{1:x} years old.", , student.age); println!("{0} is 0X{1:X} years old.", , student.age); println!("Student Pointer @{:p}!", &student); println!("Student Debug {:?}!", student);
Display
use std::fmt::{self, Display, Formatter}; struct Point { x: f32, y: f32, } // 自定义结构体打印方式 impl Display for Point { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "Display for Point(x={}, y={})", self.x, self.y) } } let p = Point { x: 0.1, y: 0.2 }; println!("{}", p); // Display for Point(x=0.1, y=0.2)

变量

变量可变性
let x = 5; println!("The value of x is: {}", x); x = 6; // Error: cannot assign twice to immutable variable println!("The value of x is: {}", x);let mut x = 5; println!("The value of x is: {}", x); x = 6; // It's ok! println!("The value of x is: {}", x);
不可变变量与常量
  • 声明常量时,必须注明值的类型
  • 常量可以在任何作用域声明,包括全局作用域。
  • 常量不能作为函数调用的结果。
const PI: f32 = 3.1415926; // It's ok const PI_2: f32 = PI / 2.0; // It's okfn get_pi() -> f32 { 3.1415926 } let pi = get_pi(); // It's ok const PI: f32 = get_pi(); // Error: cannot call non-const fn in constants
变量冻结
let mut freezing = 666; println!("freezing = {}", freezing); { #[allow(unused_variables)] let freezing = freezing; freezing = 555; //Error: cannot assign twice to immutable variable } println!("freezing = {}", freezing); freezing = 999; println!("freezing = {}", freezing);
延迟绑定
let x; x = 5; // It's ok! println!("The value of x is: {}", x); x = 6; // Error: cannot assign twice to immutable variable println!("The value of x is: {}", x);
变量隐藏
// Shadowing let x = 5; println!("The address of x is: @{:p}", &x); let x = x + 1; println!("The address of x is: @{:p}", &x); let x = x * 2; println!("The address of x is: @{:p}", &x); // The address of x is: @0xa7faac // The address of x is: @0xa7fafc // The address of x is: @0xa7fb4clet mut x = 5; println!("The address of x is: @{:p}", &x); x = x + 1; println!("The address of x is: @{:p}", &x); x = x * 2; println!("The address of x is: @{:p}", &x); // The address of x is: @0xa7faac // The address of x is: @0xa7faac // The address of x is: @0xa7faac

数据类型

基本数据类型
let _: i8; let _: u8 = b'A'; let _: u8 = 0b1111_0000; // 下划线起注释作用 let _: i16; let _: u16; let _: i32; let _: u32; let _: i64 = 98_222; // 下划线起注释作用 let _: u64; let _: i128; let _: u128; let _: isize; // 取决于操作系统位数 let _: usize; // 取决于操作系统位数 let _: f32; let _: f64; let _: char; let _: bool; // true | false println!("size(char) = {}", std::mem::size_of_val(&'A')); println!("size(bool) = {}", std::mem::size_of_val(&true)); // size(char) = 4 // size(bool) = 1
类型别名
#[allow(non_camel_case_types)] type uint64_t = u64; #[allow(non_camel_case_types)] type uint32_t = u32; let x = 0 as uint32_t; let y = 0 as uint64_t; println!("size(uint32_t) = {}", std::mem::size_of_val(&x)); println!("size(uint64_t) = {}", std::mem::size_of_val(&y)); // size(uint32_t) = 4 // size(uint64_t) = 8
简单类型转换
const NPI: f64 = -3.1415926535897f64; // Literal println!("NPI as f64 = {}", NPI); println!("NPI as f32 = {}", NPI as f32); println!("NPI as i32 = {}", NPI as i32); println!("NPI as u32 = {}", NPI as u32); // NPI as f64 = -3.1415926535897 // NPI as f32 = -3.1415927 // NPI as i32 = -3 // NPI as u32 = 0
From和into

自定义复合类型的转换方式。

#[allow(dead_code)] #[derive(Debug)] struct Number { value: i32, } impl From<i32> for Number { fn from(item: i32) -> Self { Number { value: item } } } // let num = Number::from(1111); // ↑↓ 等效 let num: Number = 1111.into(); // 必须指定类型 println!("num = {:?}", num);
String
let s1: &str = "hello"; let s2: &str = s1; println!("s1 = {:p}", s1); println!("s2 = {:p}", s2); // s1 = 0x4ba030 // s2 = 0x4ba030 let s11: String = String::from(s1); let s12: String = String::from(s1); println!("s11 = {:p}", &s11); println!("s12 = {:p}", &s12); // s11 = 0xa8fac8 // s12 = 0xa8fae0
Array
let arr: [i32; 5] = [1, 2, 3, 4, 5]; println!("len = {}", arr.len()); println!("arr = {:?}", arr); println!("arr[0] = {}", &arr[0]); // len = 5 // arr = [1, 2, 3, 4, 5] // arr[0] = 1 let arr: [i32; 10] = [0; 10]; // 10个0 println!("len = {}", arr.len()); println!("arr = {:?}", arr); println!("arr[0] = {}", &arr[0]); // len = 10 // arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] // arr[0] = 0

Array长度固定,Vector可动态扩容。

let mut v = vec![0, 1, 2]; v.push(3); let a = [0, 1, 2]; // a.push(3); // Error: method not found println!("{}, v = {:?}", v.len(), v); println!("{}, a = {:?}", a.len(), a); // 4, v = [0, 1, 2, 3] // 3, a = [0, 1, 2] // [v -> a] // 可通过迭代拷贝实现,但长度必须事先确定 // [a -> v] // let v2: Vec<i32> = a.into(); // ↑↓ 等效 // let v2 = Vec::from(a); // ↑↓ 等效 let v2 = a.to_vec(); println!("{}, v2 = {:?}", v2.len(), v2); // 3, v2 = [0, 1, 2]
Tuple
let tup: (i32, f32, u8) = (500, 6.4, 1); println!("tup = {:?}", tup); // tup = (500, 6.4, 1) println!("The value of x is: {}", tup.0); // The value of x is: 500 // Destructure let (_, y, _) = tup; println!("The value of y is: {}", y); // The value of y is: 6.4
Struct
#[allow(dead_code)] #[derive(Debug)] struct Point { x: f32, y: f32, } // 一般创建 let point1 = Point { x: 10.3, y: 0.4 }; // 复用旧结构体 let point2 = Point { y: 6.18, ..point1 }; // 同名略写 let x = 32f32; let y = 45f32; let point3 = Point { x, y }; println!("point1 = {:?}", point1); println!("point2 = {:?}", point2); println!("point3 = {:?}", point3); // point1 = Point { x: 10.3, y: 0.4 } // point2 = Point { x: 10.3, y: 6.18 } // point3 = Point { x: 32.0, y: 45.0 }
Tuple Struct
#[derive(Debug)] struct Color(u8, u8, u8); let black = Color(0, 0, 0); println!("black = {:?}", black); println!("black.0 = {}", black.0); // black = Color(0, 0, 0) // black.0 = 0

函数与表达式

// 表达式 let x = { let y = 0; y + 1 }; println!("The value of x is: {}", x); // The value of x is: 1 // 语句 let x = { let y = 0; y + 1; }; // println!("The value of x is: {}", x); // Error: `()` cannot be formatted with the default formatter// 一般函数 fn add(a: i32, b: i32) -> i32 { return a + b; } println!("add(1, 2) = {}", add(1, 2)); // 省略return fn mul(a: i32, b: i32) -> i32 { a * b } println!("mul(2, 3) = {}", mul(2, 3));

条件语句

  • 条件必须是布尔值。
  • 大括号不可省。
if false { } else if false { } else { } // 三元表达式 let r = if true { 1 } else { 0 }; println!("r = {}", r);

循环语句

while false { continue; }// 默认无限循环 loop { break; }// 遍历范围 [1, 3) for i in 1..3 { println!("{}", i); } // 遍历范围 [1, 3] for i in 1..=3 { println!("{}", i); } // 遍历列表 let a = [10, 20, 30, 40, 50]; for i in 0..5 { println!("a[{}] = {}", i, a[i]); } // 遍历对象列表 #[derive(Debug)] struct Color { r: u8, g: u8, b: u8, } let arr = [ Color { r: 128, g: 255, b: 90 }, Color { r: 0, g: 3, b: 254 }, Color { r: 0, g: 0, b: 0 }, ]; for color in arr.iter() { println!("{:?}", color); }

所有权

内存位置

引用位置
let x = 6; let r = &x;+–––––––+ │ │ +–––+–V–+–––+–│–+–––+ stack frame │ │ 6 │ │ • │ │ +–––+–––+–––+–––+–––+ [–––] [–––] x r
字符串位置
let s: &str = "Rust";s [–––––––] +–––+–––+–––+ stack frame │ • │ 4 │ │ +–│–+–––+–––+ │ │ │ preallocated +–V–+–––+–––+–––+ read-only │ R │ u │ s │ t │ memory +–––+–––+–––+–––+let s: String = String::from("Rust"); let l: &str = &s[2..]; let r: &String = &s; println!("The pointer of s is: {:p}", s.as_bytes()); // heap println!("The pointer of l is: {:p}", l); // heap // The pointer of s is: 0xb67990 // The pointer of l is: 0xb67992 println!("The pointer of &s is: {:p}", &s); // stack println!("The pointer of &l is: {:p}", &l); // stack println!("The pointer of r is: {:p}", r); // stack println!("The pointer of &r is: {:p}", &r); // stack // The pointer of &s is: 0xa8f9a8 // The pointer of &l is: 0xa8f9c0 // The pointer of r is: 0xa8f9a8 // The pointer of &r is: 0xa8f9d8+-------------------–––––-––+ | s l | [–|–––––––––] [–––––––] | +–V–+–––+–––+–––+–––+–––+–––+–│–+–––+ stack frame │ • │ 4 │ 4 │ │ • │ 2 │ │ • │ │ +–│–+–––+–––+–––+–│–+–––+–––+–––+–––+ │ │ [---] │ +-------+ r │ │ │ │ │ [–|–––––] +–V–+–––+–V–+–––+ heap │ R │ u │ s │ t │ +–––+–––+–––+–––+
默认分配位置

默认分配在栈上的内容:整数类型、浮点数类型、布尔类型、仅包含以上类型的元组。

// 实现了Copy trait: 储存在栈上 let x: i32 = 12; let y = x.clone(); // 值拷贝 let z = x; // 值拷贝(等效于上一条语句) println!("The value of z is: {}", z); // It's ok println!("The value of y is: {}", y); // It's ok println!("The value of x is: {}", x); // It's ok// 实现了Drop trait: 储存在堆上 let s1: String = String::from("sss"); let s2 = s1.clone(); // 深拷贝 let s3 = s1; // 移动(之后s1不再可用) println!("The value of s3 is: {}", s3); // It's ok println!("The value of s2 is: {}", s2); // It's ok println!("The value of s1 is: {}", s1); // Error: value borrowed here after move

所有权转移

  • 每个值都有且仅有一个所有者。
  • 当所有者离开作用域时,变量会被回收。
fn makes_copy(xx: i32) { println!("The value of xx is: {}", xx); } fn takes_reference(sr: &String) { println!("The value of sr is: {}", sr); } fn takes_ownership(ss: String) { println!("The value of ss is: {}", ss); } let x = 32; let s = String::from("hello"); println!("The value of x is: {}", x); println!("The value of s is: {}", s); makes_copy(x); // 值拷贝 println!("The value of x is: {}", x); takes_reference(&s); // 引用浅拷贝 println!("The value of s is: {}", s); takes_ownership(s); // 所有权转移(移动) println!("The value of s is: {}", s); // value borrowed here after move

引用与借用

获取值的引用,但不获取其所有权称为借用(borrowing)

fn calculate_length(s: &String) -> usize { s.len() } let s = String::from("hello"); let l = calculate_length(&s); println!("length = {}", l); // length = 5
可变引用
fn push_world(rs: &mut String) { rs.push_str(" world"); } let mut s = String::from("hello"); push_world(&mut s); println!("{}", s);

可变引用不能被连续借用

let mut s = String::from("hello"); let r1 = &mut s; // It's ok let r2 = &mut s; // Error: cannot borrow `s` as mutable more than once at a time println!("{}", r1); println!("{}", r2);

不能在混合借用可变与不可变引用

let mut s = String::from("hello"); let r1 = &s; // It's ok let r2 = &s; // It's ok let r3 = &mut s; // Error: cannot borrow `s` as mutable because it is also borrowed as immutable println!("{}", r1); println!("{}", r2); println!("{}", r3);
悬垂引用(Dangling References)

编译器可以确保数据引用不离开其作用域。

fn dangle() -> &String { // Error: expected named lifetime parameter let s = String::from("hello"); &s // 悬垂指针(dangling pointer) }
裸指针
  • 允许忽略借用规则,可以同时拥有不可变和可变的指针,或多个指向相同位置的可变指针
  • 不保证指向有效的内存
  • 允许为空
  • 不能实现任何自动清理功能
let mut num = 5; let r1 = &num as *const i32; let r2 = &mut num as *mut i32; unsafe { // 仅能在 unsafe 中解裸指针 println!("{}", *r1); println!("{}", *r2); }
切片(Slice)

切片是一种不完整的引用,类似于SQL中的视图。

let s = "0123456789A"; let l = s.len(); let all_view: &str = &s[..]; let get_left_3 = &s[..3]; let del_left_3 = &s[3..]; let get_3_6 = &s[3..6]; let get_right_3 = &s[l - 3..]; let del_right_3 = &s[..l - 3]; println!("all_view = {}", all_view); println!("get_left_3 = {}", get_left_3); println!("del_left_3 = {}", del_left_3); println!("get_3_6 = {}", get_3_6); println!("get_right_3 = {}", get_right_3); println!("del_right_3 = {}", del_right_3); // all_view = 0123456789A // get_left_3 = 012 // del_left_3 = 3456789A // get_3_6 = 345 // get_right_3 = 89A // del_right_3 = 01234567
引用生命周期
{ let a: &i32; // -------+-- 'a // | { // | let b: i32 = 5; // -+-----+-- 'b a = &b; // | | } // -+ | // | println!("a: {}", a); // | } // -------+ // Error: borrowed value does not live long enough // lifetime(b) < lifetime(a){ let b: i32 = 5; // -----+-- 'b // | let a: &i32 = &b; // --+--+-- 'a // | | println!("a: {}", a); // | | // --+ | } // -----+ // lifetime(b) > lifetime(a)

生命周期注解语法

&i32 // a reference &'a i32 // a reference with an explicit lifetime &'a mut i32 // a mutable reference with an explicit lifetime// a : 拥有确切的生命周期 // x,y : 需要与 a 的生命周期一样久 fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } }
&、ref、*
let mut val: i32 = 111; let a = &mut val; *a = 222; println!("{}", val); // 222 let ref mut b = val; *b = 333; println!("{}", val); // 333// 仅能用 & 的情况 fn only_and() { fn test(val: &mut i32) { *val = 999; } let mut x: i32 = 0; test(&mut x); println!("x = {}", x); // 999 } // 仅能用 ref 的情况 fn only_ref() { let s = Some(String::from("Hello!")); // match &s { // 此处借用s // Some(r) => println!("r = {}", r), // None => println!("None"), // } // ↑↓ 等价 match s { // 此处没有机会声明变量类型 // 只能用 ref 表示变量 r 是个指针。 Some(ref r) => println!("r = {}", r), None => println!("None"), } println!("s = {}", s.unwrap()); }
自动解引用
let a: &i32 = &123; let b: &&i32 = &a; let c: &&&i32 = &b; println!("a = {}, b = {}, c = {}", a, b, c); println!("*a = {}, **b = {}, ***c = {}", *a, **b, ***c); // a = 123, b = 123, c = 123 // *a = 123, **b = 123, ***c = 123

模式匹配

匹配数字

fn get_number_name(num: i32) { print!("{}, ", num); match num { 1 => println!("One"), 2 | 3 => println!("Two | Three"), 4..=7 => println!("Four ~ Seven"), _ => { println!("Unknow"); } } } for i in 1..=8 { get_number_name(i); } // 1, One // 2, Two | Three // 3, Two | Three // 4, Four ~ Seven // 5, Four ~ Seven // 6, Four ~ Seven // 7, Four ~ Seven // 8, Unknow

枚举类型

C Like
enum Fruit { Apple, Banana = 3, Watermelon, } println!("Fruit::Apple is {}", Fruit::Apple as i32); // use Fruit::Banana; use Fruit::{Banana, Watermelon}; // use Fruit::*; println!("Fruit::Banana is {}", Banana as i32); println!("Fruit::Watermelon is {}", Watermelon as i32); // Fruit::Apple is 0 // Fruit::Banana is 3 // Fruit::Watermelon is 4
Rust Style
#[derive(Debug)] enum Coin { Penny, Nickel, Dime, Quarter, } fn value_in_cents(coin: Coin) -> u8 { print!("Coin({:?}) = ", coin); match coin { Coin::Penny => 1, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } } println!("{}", value_in_cents(Coin::Penny)); println!("{}", value_in_cents(Coin::Nickel)); println!("{}", value_in_cents(Coin::Dime)); println!("{}", value_in_cents(Coin::Quarter)); // Coin(Penny) = 1 // Coin(Nickel) = 5 // Coin(Dime) = 10 // Coin(Quarter) = 25#[derive(Debug)] enum WebEvent { PageLoad, PageUnload, KeyPress(char), Paste(String), Click { x: i64, y: i64 }, } fn inspect(event: WebEvent) { print!("event({:?}) = ", event); match event { WebEvent::PageLoad => println!("page loaded"), WebEvent::PageUnload => println!("page unloaded"), WebEvent::KeyPress(c) => println!("pressed '{}'.", c), WebEvent::Paste(s) => println!("pasted \"{}\".", s), WebEvent::Click { x, y } => { println!("clicked at x={}, y={}.", x, y); } } } inspect(WebEvent::PageLoad); inspect(WebEvent::KeyPress('x')); inspect(WebEvent::Paste("my text".to_owned())); inspect(WebEvent::Click { x: 20, y: 80 }); inspect(WebEvent::PageUnload); // event(PageLoad) = page loaded // event(KeyPress('x')) = pressed 'x'. // event(Paste("my text")) = pasted "my text". // event(Click { x: 20, y: 80 }) = clicked at x=20, y=80. // event(PageUnload) = page unloaded
Option

Rust并没有空值,取而代之的是Option<T>,其被定义为:

enum Option<T> { Some(T), None, }

如果使用None而不是Some,需要告诉RustOption<T>是什么类型的。

let num = Some(5); let val = match num { Some(i) => i, None => -1, }; let absent: Option<i32> = None; println!("is_some = {}, val = {}", num.is_some(), val); println!("is_none = {}", absent.is_none()); // is_some = true, val = 5 // is_none = true
if let
let num = Some(5); if let Some(i) = num { println!("If matched `{}`!", i); } // If matched `5`!while let Some(i) = num { println!("While matched `{}`!", i); break; } // While matched `5`!#[allow(dead_code)] enum Coin { Penny, Nickel, Dime, Quarter, } let coin = Coin::Penny; if let Coin::Penny = coin { println!("A Penny!"); } // A Penny!

错误处理

错误分类:

  • 可恢复错误(recoverable):Result<T, E>
  • 不可恢复错误(unrecoverable):panic!

panic!

程序会打印出一个错误信息,展开并清理栈数据,然后接着退出。

pub fn main() { // 手动造成一个 panic panic!("crash and burn"); // process didn't exit successfully }pub fn main() { // panic 由其它库抛出 let v = vec![1, 2, 3]; v[99]; // process didn't exit successfully }

Result

Result被定义为:

enum Result<T, E> { Ok(T), Err(E), }
错误判断
use std::io::Result; use std::fs::File; const FILE_PATH: &str = "test.txt"; let fr: Result<File> = File::open(FILE_PATH); if fr.is_ok() { println!("Opened"); } if fr.is_err() { println!("Error is {:?}", fr.err().unwrap()); // Error is Os { code: 2, kind: NotFound, message: "系统找不到指定的文件。" } }
错误类型
use std::io::{Result, ErrorKind, Write}; use std::fs::File; const FILE_PATH: &str = "test.txt"; let f: Result<File> = File::open(FILE_PATH); #[allow(unused_variables)] let f: File = match f { Ok(f) => f, // match guard: 这个条件必须为真才能使分支的代码被执行 Err(ref e) if e.kind() == ErrorKind::NotFound => { // 创建一个文件 match File::create(FILE_PATH) { Ok(mut fc) => { fc.write("Hello Test!".as_bytes()).unwrap(); fc } Err(ec) => { panic!("Error is {:?}", ec) } } } Err(e) => { panic!("Error is {:?}", e) } };
简化Result展开

unwrap和expect可简化match Result<T>。

use std::io::{Result, ErrorKind}; use std::fs::File; const FILE_PATH: &str = "test.txt"; let f: Result<File> = File::open(FILE_PATH); let f: File = match f { Ok(f) => f, Err(e) => panic!("{}", e), }; // ↑↓ let f: File = File::open(FILE_PATH).unwrap(); // ↑↓ let f: File = File::open(FILE_PATH).expect("Error"); // 自定义panic信息
传播错误

选择让调用者知道这个错误并决定该如何处理,这被称为传播(propagating)错误

use std::io::{Result, Read}; use std::fs::File; const FILE_PATH: &str = "hello.txt"; fn propagating() -> Result<String> { let mut file = match File::open(FILE_PATH) { Ok(f) => f, Err(e) => return Err(e), // 函数返回 }; let mut buff = String::new(); match file.read_to_string(&mut buff) { Ok(_) => Ok(buff), // 函数返回 Err(e) => Err(e), // 函数返回 } } let t = propagating(); if t.is_ok() { let s = t.unwrap(); println!("{}", s); } else { let e = t.err().unwrap(); println!("{:?}", e); }// 传播简写 fn propagating() -> Result<String> { let mut buff = String::new(); let mut file = File::open(FILE_PATH)?; // 返回T || 返回 Err(e) file.read_to_string(&mut buff)?; // 返回T || 返回 Err(e) Ok(buff) }// 传播简简写 fn propagating() -> Result<String> { let mut buff = String::new(); File::open(FILE_PATH)?.read_to_string(&mut buff)?; Ok(buff) }

泛型与特性

实现(Implementation)

#[allow(dead_code)] #[derive(Debug)] struct Point { x: f32, y: f32, } // 在结构体域上实现方法 impl Point { // 修改当前实例的对象 fn add_to_point(&mut self, p2: &Point) { self.x += p2.x; self.y += p2.y; } // 获取实例的所有权,生成新对象 fn add_new_point(self, p2: &Point) -> Point { Point { x: self.x + p2.x, y: self.y + p2.y } } // 关联函数:不含self fn from_xy(x: f32, y: f32) -> Point { Point { x, y } } } let p1 = Point::from_xy(2.0, 3.0); let mut p2 = Point { x: 23.0, y: 22.0 }; (&mut p2).add_to_point(&p1); // 手动解引用 p2.add_to_point(&p1); // 自动解引用, println!("p2 = {:?}", p2); // p2 = Point { x: 27.0, y: 28.0 } let p3 = p2.add_new_point(&p1); // println!("p2 = {:?}", p2); // Error: value borrowed here after move println!("p3 = {:?}", p3); // p3 = Point { x: 29.0, y: 31.0 }

特性(Trait)

类似于Java中的接口。

// interface-like trait Walkable { fn walk(&self); fn echo(&self) { // 默认实现 println!("echo!"); } } // class-like struct People {} impl Walkable for People { fn walk(&self) { println!("People walk!"); } fn echo(&self) { println!("People echo!"); } } // class-like struct Animal {} impl Walkable for Animal { fn walk(&self) { println!("Animal walk!"); } } let p = People{}; let a = Animal{}; p.walk(); p.echo(); a.walk(); a.echo(); // People walk! // People echo! // Animal walk! // echo!
特性组合
trait Walkable { fn walk(&self); } trait Runnable { fn run(&self); } // 组合 trait Walk2Runnable: Walkable + Runnable { fn walk_2_run(&self); } struct People {} impl Walkable for People { fn walk(&self) { print!("walk"); } } impl Runnable for People { fn run(&self) { print!("run"); } } // 如果要实现Walk2Runnable,必须实现Walkable和Runnable impl Walk2Runnable for People { fn walk_2_run(&self) { self.walk(); print!("->"); self.run(); } } let p = People{}; p.walk_2_run(); // walk->run
运算符重载
use std::ops::Add; #[derive(Debug, PartialEq)] struct Point { x: i32, y: i32, } impl Add for Point { type Output = Point; fn add(self, other: Point) -> Point { Point { x: self.x + other.x, y: self.y + other.y, } } } let p = Point { x: 1, y: 0 } + Point { x: 2, y: 3 }; println!("{:?}", p);
特性实现重叠
trait Pilot { fn fly(&self); } trait Wizard { fn fly(&self); } struct Human; impl Pilot for Human { fn fly(&self) { println!("This is your captain speaking."); } } impl Wizard for Human { fn fly(&self) { println!("Up!"); } } let person = Human; Pilot::fly(&person); Wizard::fly(&person); person.fly(); // Error: multiple applicable items in scope

泛型(Generic)

struct Point<T> { x: T, y: T, } impl<T> Point<T> { fn x(&self) -> &T { &self.x } fn y(&self) -> &T { &self.y } } let p = Point { x: 5, y: 10 }; println!("p.x = {}, p.y = {}", p.x(), p.y());enum Boolean<T, F> { True(T), False(F), }

trait bound:只为实现了特定trait的类型的结构实现方法。

// 方式一 fn largest<T: PartialOrd + Copy>(a: &[T]) -> T { let mut n = a[0]; for &i in a.iter() { if i > n { n = i; } } n }// 方式二 fn largest<T>(a: &[T]) -> T where T: PartialOrd + Copy { let mut n = a[0]; for &i in a.iter() { if i > n { n = i; } } n }let n_arr = vec![34, 50, 25, 100, 65]; let c_arr = vec!['y', 'm', 'a', 'q']; let result = largest(&n_arr); println!("The largest number is {}", result); let result = largest(&c_arr); println!("The largest char is {}", result);

模拟重载(Overload)

Rust中trait From被定义为:

pub trait From<T>: Sized { fn from(value: T) -> Self; }

String对其的两个实现为:

impl From<char> for String { fn from(c: char) -> Self { c.to_string() } } impl From<&str> for String { fn from(s: &str) -> String { s.to_owned() } }

通过泛型和特性实现的重载功能:

let s1 = String::from('A'); let s2 = String::from("A");

多态

泛型为单态化处理,所产生的代码进行静态分发(static dispatch),这与**动态分发(dynamic dispatch)**相对。dyn关键字表示具体类型已被擦去,一个dyn引用包含两个指针:

  • 指向数据
  • 指向方法调用名称与函数指针的映射
// Draw特性 pub trait Draw { fn draw(&self); } // 屏幕上是可Draw组件 pub struct Screen { // 类型擦除 pub components: Vec<Box<dyn Draw>>, } impl Screen { // 屏幕运行时,绘制所有可Draw组件 pub fn run(&self) { for component in self.components.iter() { // 基于泛型和Trait实现的多态。 component.draw(); } } } // Button可Draw pub struct Button { /* ... */ } impl Draw for Button { fn draw(&self) { println!("draw Button") } } // Label可Draw pub struct Label { /* ... */ } impl Draw for Label { fn draw(&self) { println!("draw Label") } } let screen = Screen { components: vec![Box::new(Label {}), Box::new(Button {})], }; screen.run();

Collection

use std::vec; use std::collections::{ VecDeque, LinkedList, HashMap, HashSet, BTreeMap, BTreeSet, BinaryHeap, };

Vector

let mut vec_u8: Vec<u8> = Vec::new(); vec_u8.push(77u8); vec_u8.push(99u8); println!("vec_u8 = {:?}", vec_u8); for i in &vec_u8 { println!("{}", i); } // 容器自动推断 let mut vec_auto = Vec::new(); vec_auto.push(66u8); vec_auto.push(88u8); for i in &mut vec_auto { *i -= 2; } println!("vec_auto = {:?}", vec_auto);

HashMap

use std::collections::HashMap; let mut kv1 = HashMap::new(); kv1.insert("Blue", 10); kv1.entry("Yellow").or_insert(50); kv1.entry("Blue").or_insert(50); println!("{:?}", kv1); let mut kv2: HashMap<i32, String> = HashMap::new(); kv2.insert(0, String::from("A")); kv2.insert(1, String::from("B")); kv2.insert(2, String::from("C")); println!("{:?}", kv2);

IO

命令行

命令行参数
use std::env; let args: Vec<String> = env::args().collect(); println!("len = {}", args.len()); println!("args = {:?}", args); println!("args[0] = {}", &args[0]);
命令行输入
use std::io::stdin; let mut buff = String::new(); stdin().read_line(&mut buff) .expect("Failed to read line."); println!("input is {}", buff);
读取环境变量
use std::env; let v = env::var("PATH").unwrap(); println!("PATH = {}", v);

读写文件

文件写入
use std::fs; const FILE_PATH: &str = "test.txt"; fs::write(FILE_PATH, "FROM RUST PROGRAM").unwrap();use std::fs::File; const FILE_PATH: &str = "test.txt"; let mut f = File::create(FILE_PATH).unwrap(); f.write("FROM RUST PROGRAM".as_bytes());use std::fs::OpenOptions; use std::io::Write; const FILE_PATH: &str = "test.txt"; let mut file = OpenOptions::new() .append(true).open(FILE_PATH).unwrap(); file.write(b" APPEND WORD").unwrap();
文件读取
use std::fs; const FILE_PATH: &str = "test.txt"; let text = fs::read_to_string(FILE_PATH).unwrap(); println!("{}", text);use std::fs; const FILE_PATH: &str = "test.txt"; let content_bytes = fs::read(FILE_PATH).unwrap(); String::from(); let content = String::from_utf8(content_bytes).unwrap(); println!("{}", content);use std::io::Read; use std::fs::File; const FILE_PATH: &str = "test.txt"; let mut f = File::open(FILE_PATH).unwrap(); let mut buff = [0u8; 64]; let len = f.read(&mut buff).unwrap(); println!("len = {}", len); let content = Vec::from(&buff[..len]); let content = String::from_utf8(content).unwrap(); println!("content = {}", content);

函数式编程

Closure

Lambda表达式
  • |arg0: ParameterType, ...| -> FunctionType { ... }
  • |arg0: ParameterType, ...| ...
  • |arg0, ...| ..
  • || ...
// lambda(完整) let ladd1 = |x: i32, y: i32| -> i32 { x + y }; println!("ladd1(2, 3) = {}", ladd1(2, 3)); // lambda(省略返回类型) let ladd2 = |x: i32, y: i32| x + y; println!("ladd2(2, 3) = {}", ladd2(2, 3)); // lambda(省略变量类型、返回类型) let ladd3 = |x, y| x + y; println!("ladd3(2, 3) = {}", ladd3(2, 3)); // lambda(无参数) let r = || 32; println!("{}", r());
所有权捕获
use core::ops::{FnOnce, FnMut, Fn}; // 实际使用中往往由编译器推断确定。

FnOnce移动捕获:闭包只能被调用一次。

let s = String::new(); let f = move || -> String { // move关键字可以省略 let mut c = s; // 所有权转移(入) c.push_str("+"); c // 所有权转移(出) }; // println!("s = {}", s); // Error: borrow of moved value: `s` println!("f() = {}", f()); // It's ok // println!("f() = {}", f()); // Error: borrow of moved value: `s` // println!("s = {}", s); // Error: borrow of moved value: `s`

FnMut可变借用捕获

let mut s = String::new(); let mut f = || { s.push_str("+"); }; f(); f(); f(); // It's ok println!("s = {}", s); // It's ok

Fn不可变借用捕获

let w = "word"; let f = || -> String { let mut s = String::new(); s.push_str(w); s }; println!("s = {}", f()); // It's ok println!("s = {}", f()); // It's ok

Iterator

Rust中Iterator被定义为

// use std::iter::Iterator; trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; // ... }
消费迭代器
// use std::vec::Vec; use core::slice::Iter; // impl FusedIterator : Iterator use core::iter::Map; // impl FusedIterator : Iterator let a: Vec<i32> = vec![1, 2, 3]; let a_it: Iter<i32> = a.iter(); let a_map: Map<Iter<i32>, fn(&i32) -> i32> = a_it.map(|x: &i32| -> i32 { x * 2 }); for it in a_map.clone() { print!("it = {}, ", it); } println!(); let a_coll: Vec<i32> = a_map.clone().collect(); println!("a_coll = {:?}", a_coll); let a_sum: i32 = a_map.sum(); println!("a_sum = {}", a_sum); // it = 2, it = 4, it = 6, // a_coll = [2, 4, 6] // a_sum = 12
自定义迭代器
struct CounterIter { start_num: i32, end_num: i32, } impl CounterIter { fn new(start_num: i32, end_num: i32) -> CounterIter { CounterIter { start_num, end_num } } } impl Iterator for CounterIter { type Item = i32; fn next(&mut self) -> Option<Self::Item> { if self.start_num >= self.end_num { return None; } let r = Some(self.start_num); self.start_num += 1; r } } for item in CounterIter::new(0, 6) { print!("{}, ", item); } // 0, 1, 2, 3, 4, 5,

智能指针

指针类型

Box

Box允许你将一个值放在堆上而不是栈上,留在栈上的则是指向堆数
据的指针。

let b = Box::new(5); println!("b = {}", b);
Rc

引用计数。

enum List { Cons(i32, Rc<List>), Nil, } use List::{Cons, Nil}; use std::rc::Rc; let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil))))); println!("count after creating a = {}", Rc::strong_count(&a)); let b = Cons(3, Rc::clone(&a)); println!("count after creating b = {}", Rc::strong_count(&a)); { let c = Cons(4, Rc::clone(&a)); println!("count after creating c = {}", Rc::strong_count(&a)); } println!("count after c goes out of scope = {}", Rc::strong_count(&a)); // count after creating a = 1 // count after creating b = 2 // count after creating c = 3 // count after c goes out of scope = 2
Cell&RefCell

Cell和RefCell在功能上没有区别,区别在于Cell<T>适用于T实现Copy的情况。

使用RefCell<T>能够在外部值被认为是不可变的情况下修改内部值。Box<T>借用规则的不可变性作用于编译时。对于RefCell<T>,这些不可变性作用于运行时。

use std::cell::Cell; let c = Cell::new("asd"); println!("c = {}", c.get()); c.set("qwe"); // 此处违反借用规则,但可运行 println!("c = {}", c.get());

RefCell实际上并没有解决可变引用和引用可以共存的问题。

use std::cell::RefCell; let s = RefCell::new(String::from("hello, world")); let bi = s.borrow(); let bm = s.borrow_mut(); println!("{}, {}", bi, bm); // 没有编译器错误 // 存在运行时错误: already borrowed: BorrowMutError
Weak

弱引用,通常和Rc协同使用解决引用循环问题。

递归类型

enum List { Cons(i32, List), // Error: recursive type `List` has infinite size Nil, } use List::{Cons, Nil}; let _ = Cons(1, Cons(2, Cons(3, Nil)));

使用智能指针进行递归存储:

enum List { Cons(i32, Box<List>), Nil, } use List::{Cons, Nil}; let _ = Cons( 1, Box::new(Cons( 2, Box::new(Cons( 3, Box::new(Nil))))));

Deref

智能指针自动解引用。

struct MyBox<T>(T); impl<T> MyBox<T> { fn new(x: T) -> MyBox<T> { MyBox(x) } } let val = MyBox::new(5); // println!("{}", *val); // Error: type `MyBox<{integer}>` cannot be dereferenced use std::ops::Deref; impl<T> Deref for MyBox<T> { type Target = T; fn deref(&self) -> &T { &self.0 } } println!("{}", *val); // ↑↓ 等价 println!("{}", *(val.deref()));

Drop

离开作用域时操作代码。

struct CustomSmartPointer { data: String, } impl Drop for CustomSmartPointer { fn drop(&mut self) { println!("Dropping `{}`!", self.data); } } let _a = CustomSmartPointer { data: String::from("A") }; let _b = CustomSmartPointer { data: String::from("B") }; println!("Created!"); // Created! // Dropping `B`! // Dropping `A`!

Module

代码

说明

mod ...;

引入同级模块文件

mod ... {}

创建文件内模块

use crate::...;

引入同级模块方法

crate::...();

调用同级模块内方法

self::...();

调用当前模块内方法

单文件

fn say_hello() { println!("Hello mod_module!"); } // 自定义模块 mod demo_module { // private fn say_hello() { println!("Hello demo_module!"); } // public pub fn hello() { // 调用私有方法 self::say_hello(); // 调用包含当前模块的模块内方法 super::say_hello(); } } pub fn main() { demo_module::hello(); use demo_module::hello; hello(); }

多文件

main.rs

mod mod_test0; mod mod_test1; fn main() { mod_test0::hello(); mod_test1::hello(); mod_test1::mod_sub::hello(); // mod_test0 hello // mod_test1 hello // mod_sub hello use mod_test0::hello as hello0; use mod_test1::hello as hello1; use mod_test1::{ mod_sub }; use mod_sub::*; hello0(); hello1(); mod_sub::hello(); hello(); // mod_test0 hello // mod_test1 hello // mod_sub hello // mod_sub hello }

mod_test0.rs

pub fn hello() { println!("mod_test0 hello"); }

mod_test1/mod.rs

pub mod mod_sub; pub fn hello() { println!("mod_test1 hello"); }

mod_test1/mod_sub.rs

pub fn hello() { println!("mod_sub hello"); }

Macro

macro_rules! MacroName { ($arg0: ArguementType) => {...}; ... }
  • 宏被调用时,会由上而下对每个规则进行匹配
  • 宏调用所使用的括号可以是()、[]、{}任意一种

使用$( ... ) [sep] */+/?可以进行重复匹配

ArguementType

Note

Example

item

函数定义或常量声明

block

{ ... }

stmt

语句

let x = 32

pat

模式

Some(a)

expr

表达式

Vec::new()

ty

类型

i32

ident

标识符或关键字

i、self

path

模块路径

std::result::Result

tt

Token树

meta

属性

#[...]

lifetime

生命周期Token

static

vis

可能为空的限定符

pub

literal

字面量

macro_rules! build_vec { ( $( $i:expr ) , * // 重复匹配表达式 $( , )? // 可选的末尾逗号 ) => { { // 表达式 let mut vec = Vec::new(); $( vec.push($i); )* // 重复添加 vec // 返回 } } } let vs = build_vec!(1, 1 + 2, 2 + 3, ); println!("vs = {:?}", vs); // vs = [1, 3, 5]

unsafe

需要unsafe的场景:

  • 解裸指针*const i32、*mut i32
  • 调用unsafe fn
  • 调用extern中内容
  • 访问或修改static mut变量
  • 实现unsafe trait
unsafe fn dangerous() {} unsafe { dangerous(); }extern "C" { fn abs(input: i32) -> i32; } fn main() { unsafe { println!("Absolute value of -3 according to C: {}", abs(-3)); } }static mut COUNTER: u32 = 0; unsafe { COUNTER += 1; println!("COUNTER: {}", COUNTER); }

Thread

use std::thread::{self, JoinHandle}; use std::time::Duration; // 子线程 let handle: JoinHandle<_> = thread::spawn(|| { for i in 1..10 { println!("spawn thread: {}", i); thread::sleep(Duration::from_millis(1)); } }); // 主线程 for i in 1..5 { println!("main thread: {}", i); thread::sleep(Duration::from_millis(1)); } // 当<主线程>结束时,<子线程>也会结束

join

主线程等待子线程执行完毕。

use std::thread::{self, JoinHandle}; use std::time::Duration; // 子线程 let handle: JoinHandle<_> = thread::spawn(|| { for i in 1..10 { println!("spawn thread: {}", i); thread::sleep(Duration::from_millis(1)); } }); // 主线程 for i in 1..5 { println!("main thread: {}", i); thread::sleep(Duration::from_millis(1)); } // 当<主线程>结束时,等待<子线程>结束 handle.join().unwrap();use std::thread::{self, JoinHandle}; use std::time::Duration; // 子线程 let handle: JoinHandle<_> = thread::spawn(|| { for i in 1..10 { println!("spawn thread: {}", i); thread::sleep(Duration::from_millis(1)); } }); // 等待<子线程>结束,再开始运行<主线程> handle.join().unwrap(); // 主线程 for i in 1..5 { println!("main thread: {}", i); thread::sleep(Duration::from_millis(1)); }

channel

通道为单所有权,数据传入通道后将无法再使用。

use std::thread; use std::sync::mpsc; let (sender, receiver) = mpsc::channel(); thread::spawn(move || { let val = String::from("hi"); sender.send(val).unwrap(); }); // 阻塞并接收值 let received = receiver.recv().unwrap(); println!("{}", received);use std::thread; use std::sync::mpsc; use std::time::Duration; let (sender, receiver) = mpsc::channel(); thread::spawn(move || { let val_list = vec![ String::from("hi"), String::from("from"), String::from("the"), String::from("thread"), ]; for val in val_list { sender.send(val).unwrap(); thread::sleep(Duration::from_secs(1)); } }); // 阻塞并接收值 for received in receiver { println!("- {}", received); }

Mutex & Arc

在智能指针特性方面:

  • Mutex<T>类似于RefCell<T>
  • Arc<T>类似于Rc<T>

Mutex<T>和Arc<T>为多所有权。

use std::sync::{Mutex, MutexGuard}; let mutex = Mutex::new(5); { // 获取锁,返回可写智能指针(MutexGuard) let mut num: MutexGuard<_> = mutex.lock().unwrap(); *num = 6; // 退出作用域时自动释放锁 } println!("m = {:?}", mutex); // m = Mutex { data: 6, poisoned: false, .. }

Sync & Send

// Rust 中的两个空实现 trait use std::marker::{Sync, Send};

Send表明类型的所有权可以在线程间传递。除了Rc<T>外,几乎所有的Rust类型都是Send的。

Sync表明一个实现了Sync的类型可以安全的在多个线程中拥有其值的引用。Rc<T>、RefCell<T>、Cell<T>不是Sync的。

Socket

Tcp

tcp_server/main.rs

use std::io::{Read, Write}; use std::net::{TcpListener, TcpStream}; fn handle_client(mut stream: TcpStream) { let mut buffer = [0u8; 128]; loop { // 读取消息 let length = stream.read(&mut buffer).unwrap(); let content = std::str::from_utf8(&buffer[..length]).unwrap(); println!("{}, content = {}", length, content); // 回复消息 let message = format!("received: {}", content); stream.write(message.as_bytes()).unwrap(); stream.flush().unwrap(); } } fn main() { let listener = TcpListener::bind("127.0.0.1:8888").unwrap(); // 对每一个连接开启一个线程进行处理 for stream in listener.incoming() { std::thread::spawn(move || { handle_client(stream.unwrap()); }); } }

tcp_client/main.rs

use std::io::{self, Read, Write}; use std::net::TcpStream; fn main() { let mut stream = TcpStream::connect("127.0.0.1:8888").unwrap(); let mut length: usize; let mut buffer = [0u8; 128]; loop { // 从命令窗口读取消息 length = io::stdin().read(&mut buffer).unwrap(); stream.write(&buffer[..length]).unwrap(); stream.flush().unwrap(); // 查看消息 let length = stream.read(&mut buffer).unwrap(); let content = std::str::from_utf8(&buffer[..length]).unwrap(); println!("{}, content = {}", length, content); } }

UdpBroadcast

udp_broadcast_server/main.rs

use std::net::{SocketAddr, UdpSocket, Ipv4Addr}; fn main() { let bind_socket_address = SocketAddr::from("0.0.0.0:8888"); let multi_address = Ipv4Addr::new(234, 2, 2, 2); let socket = UdpSocket::bind(bind_socket_address).unwrap(); let mut buffer = [0u8; 65535]; socket.join_multicast_v4(&multi_address, &Ipv4Addr::UNSPECIFIED).unwrap(); loop { let (size, source_address) = socket.recv_from(&mut buffer).unwrap(); let message = std::str::from_utf8(&buffer).unwrap(); println!("Received {} bytes from {:?}", size, source_address); println!("message = {}", &message[..size]); } }

udp_broadcast_client/main.rs

use std::net::{Ipv4Addr, SocketAddr, UdpSocket}; fn main() { let bind_socket_address = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 9999)); let multi_socket_address = SocketAddr::from(([234, 2, 2, 2], 8888)); let socket = UdpSocket::bind(bind_socket_address).unwrap(); let message = "Hello Udp Broadcast!"; socket.send_to(message.as_bytes(), multi_socket_address).unwrap(); }


    你可能想看:

    扫描二维码推送至手机访问。

    版权声明:本文由皇冠云发布,如需转载请注明出处。

    本文链接:https://www.idchg.com/info/30692.html

    分享给朋友:

    “windows2019 自建rustdesk服务器” 的相关文章

    云桌面是什么?解锁现代工作与学习的新方式

    云桌面是一个令人兴奋的概念,尤其是在如今这个数字化迅速发展的时代。我个人认为,云桌面不仅仅是一项技术,更是一种全新的工作方式。简单来说,云桌面是一种基于云计算的桌面虚拟化解决方案。它允许用户通过互联网随时随地访问一个在云端运行的桌面环境。想象一下,不论你在咖啡馆、家中还是办公室,只需一台设备和网络连...

    Oracle 免费VPS:轻松入门云计算的最佳选择

    在了解Oracle免费VPS之前,先来看看Oracle Cloud。这是甲骨文公司推出的一项云服务,提供了一系列强大的计算和存储资源。Oracle Cloud的最吸引人的部分是它的免费服务,给用户提供了机会,可以在没有经济负担的情况下体验云计算的强大功能。对于开发者、创业者或只是想进行一些小项目的用...

    BBR对国内网站的实际作用与应用效果分析

    BBR(Bottleneck Bandwidth and Round-trip propagation time)算法是由Google推出的一种TCP拥塞控制算法。它的设计初衷是为了优化网络连接的传输速率和稳定性,尤其是在面临高延迟和波动网络条件时表现优异。可能的很多朋友会问,BBR到底是个什么东西...

    如何选择和管理SSL证书提升网站安全性

    在这个数字化迅速发展的时代,数据安全显得愈发重要。SSL证书(Secure Socket Layer Certificate)是一种专门设计用于保护互联网上数据传输安全的数字证书。说起SSL证书,首先,它是通过遵循SSL协议来实现的,由值得信赖的数字证书颁发机构(CA)在验证服务器身份之后签发。这样...

    如何安全地开放所有端口并规避网络风险

    我第一次接触网络配置的时候,看到“开放所有端口”这个词,心里有些忐忑。其实,开放端口是网络通信中非常基础的概念。简单来说,端口就像是网络中的开口,允许不同的应用程序和服务进行数据交换。每个端口都有其独特的号码,从1到65535不等,其中小于1024的端口通常用于系统服务,而大于1024的端口就属于应...

    买域名的全流程攻略:从选择到安全管理

    购买域名是一项非常重要的投资,尤其对于那些希望在网上建立品牌或个人网站的人来说。域名不仅仅是一个网址,它是你在线身份的象征。因此,了解如何选择和购买域名显得极为关键。 选择域名时,需要考虑多个因素。首先,域名应该简洁易记,便于用户输入和分享。其次,关键字的相关性也非常重要,因为一个包含行业相关关键词...