- P253的图展示了网络各层用到的协议
Box<dyn std::error::Error>
表示一个指针指向的实现了标准错误库的类型,dyn
表明这是一个特征对象(trait object),是rust里多态的一种实现方式;- 特征对象和模板对象(generics)都是rust实现多态的方式,模板属于静态分发(static dispatch),需要更多的磁盘空间(disk space),但是更快(faster funtime);特征对象(trait object)属于动态分发(dynamic dispatch),运行时需要的空间更小但会引入一点运行时的开销(间接指针的寻址开销);
- 在rust里特征对象有三种形式,
&dyn Trait, &mut dyn Trait, Box<dyn Trait>
,主要区别是Box<dyn Trait>
是有所有权的对象(owned trait object),另外两种是借用(borrowed)的,旧版本中还有&Trait, Box<Trait>
表示特征对象,现在已经弃用,在函数返回值封装错误成Box<dyn Trait>
的原因是Box的大小已知,可以存放在栈上; - 8.3节后面大部分通过一个简单的RPG游戏来介绍特征对象;
- 8.4节讲了如何使用标准库中
std::net::TcpStream
来创建tcp连接,以及使用trust_dns库来解析域名;通常绑定本地地址为0.0.0.0:0
,表示在本机由OS挑选一个随机的端口来创建连接; - 使用
Vec::with_capacity(512)
和vec![0;512]
来创建Vec<T>的区别在于前者的长度为0,容量为512,后者的长度和容量都是512; - 问号
?
在一个返回Result<T,E>的函数结尾是一个语法糖,作为try!
宏的缩写形式,当返回结果是Ok(T)的时候返回T,返回Err(err)的时候,try! / ?
提前返回并且尝试将err转化成调用函数返回值的Error类型; - 为一个新的类型实现
std::error::Error
可以在实现部分留空,因为在std::error::Error
里有默认实现,map_err(f)
中会把一个error类型映射(map)到一个函数(function)中,在这里一个实现了std::error::Error
的枚举错误类型可以看做是一个function; - 如果不想使用
map_err()
,可以为自己的Error类型实现std::convert::From
来减少过于冗长的代码;还有一种应对多种Error类型返回值的方法就是使用unwrap()
或者expect()
,但这种方法不推荐给库作者,因为使用库的用户可能会碰到意想不到崩溃; - MAC地址有6个字节,分为全球地址(universally administered address)和局域地址(locally administered address),全球地址在MAC地址的前3个字节里,表示组织编号,而局域地址的6个字节都是设备编号;
- MAC地址有单播(unicast)和广播(multicast)两种模式,区别在于单播只会让目标MAC地址收到数据帧(frame),设置方法是在MAC地址第一个字节的最低位,设为1表示广播模式,下图比较清晰的阐释了两种模式的区别:
- 8.9节介绍了用ip tuntap工具来创建虚拟网络设备,必须在Linux环境下运行,详见Page282;8.10节从命令行参数处理、MAC地址生成、DNS解析、用TCP原语发起HTTP请求,实现了一个比较底层的网络处理工具;