Rust网络编程(3)-ipnet、mio、pnet、dns和serde介绍

ipnet、mio、pnet和dns介绍

1. ipnet

无类别域间路由
说白了就是带有掩码管理Ip
ipnet,更好的管理IP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use std::net::{Ipv4Addr,Ipv6Addr};
use ipnet::{IpNet, Ipv4Net, Ipv6Net};
use std::str::FromStr;
fn main()-> std::io::Result<()> {
let _v4 = Ipv4Net::new(Ipv4Addr::new(10,1,1,0),24).unwrap();
let _v6 = Ipv6Net::new(Ipv6Addr::new(0xfd,0,0,0,0,0,0,0),24).unwrap();
let _v4 = Ipv4Net::from_str("10.1.1.0/24").unwrap();
let _v6 = Ipv6Net::from_str("fd00::/24").unwrap();

let _v4: Ipv4Net = "10.1.1.0/24".parse().unwrap();
let _v6: Ipv6Net = "fd00::/24".parse().unwrap();

let _net = IpNet::from(_v4);
let _net = IpNet::from_str("10.1.1.0/24").unwrap();
let net: IpNet = "10.1.1.0/24".parse().unwrap();
println!("{}, hostmask = {}",net,net.hostmask());
println!("{}, netmask = {}",net,net.netmask());

assert_eq!("192.168.12.34/16".parse::<IpNet>().unwrap().trunc(),"192.168.0.0/16".parse().unwrap());
Ok(())
}

2. mio

通俗的说,就是异步网络IO框架,可以理解为是个消息队列(类似golang中的nsq)
mio是rust实现的一个轻量级的I/O库。其实现基本上就是对不同操作系统底层相关API的封装,抽象出统一的接口供上层使用。
重要特性:
非阻塞TCP,UDP
I/O事件通知epoll,kqeue,IOCP实现
运行时零分配
平台可扩展
引入依赖:mio={version="0.7.0",features=["os-poll","tcp"]}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
use mio::net::{TcpListener, TcpStream};
use mio::{Events,Interest,Poll,Token};

const SERVER: Token = Token(0);
const CLIENT: Token = Token(1);

fn main() ->std::io::Result<()>{
//服务器端
let mut poll = Poll::new()?;
let mut events = Events::with_capacity(128);
let addr = "127.0.0.1:8080".parse().unwrap();
let mut server = TcpListener::bind(addr)?;
poll.registry().register(&mut server,SERVER,Interest::READABLE)?;


//客户端
let mut client = TcpStream::connect(addr)?;
poll.registry().register(&mut client,CLIENT,Interest::READABLE |Interest::WRITABLE)?;

loop{
poll.poll(&mut events,None)?;
for event in events.iter(){
match event.token(){
SERVER =>{
let connection = server.accept();
println!("SERVER recv a connection!");
drop(connection);
}
CLIENT =>{
if event.is_writable(){
println!("Client write");
}
if event.is_readable(){
println!("Client read");
}
return Ok(())
}
_ => unreachable!(),
}
}
}
}

3 pnet

为Rust提供一组跨平台的底层网络API
案例:监听网卡信息(数据从本地传到哪里)
以下代码执行后,需要sudo才能读取网卡信息。
cargo传入参数:cargo run -- en0,传入网卡名称
执行时,需要到debug找到二进制文件,并sudo执行:sudo ./use_pnet en0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use pnet::datalink::Channel::Ethernet;
use pnet::datalink::{self, NetworkInterface};
use pnet::packet::ethernet::{EthernetPacket, EtherTypes};
use pnet::packet::ip::IpNextHeaderProtocols;
use pnet::packet::ipv4::Ipv4Packet;
use pnet::packet::tcp::TcpPacket;
use pnet::packet::Packet;

use std::env;

fn main() {
//终端输入的网卡名称
let interface_name = env::args().nth(1).unwrap();

//获取网卡列表
//判断网卡列表里是否有终端输入的网卡名称
let interfaces = datalink::interfaces();
let interface = interfaces
.into_iter()
.filter(|iface: &NetworkInterface| iface.name == interface_name)
.next()
.expect("Error get interface");
println!("{}",interface);
//_tx 接收(忽略) rx 发送(该案例关注)
let (_tx, mut rx) = match datalink::channel(&interface, Default::default()) {
Ok(Ethernet(tx, rx)) => (tx, rx),
Ok(_) => panic!("Other"),
Err(e) => panic!("error:{}", e),
};
//读取从网卡发送消息
loop {
match rx.next() {
Ok(packet) => {
let packet = EthernetPacket::new(packet).unwrap();
handle_packet(&packet);
}
Err(e) => {
println!("Some error: {}", e);
}
}
}
}

fn handle_packet(ethernet: &EthernetPacket) {
match ethernet.get_ethertype() {
EtherTypes::Ipv4 => {
let header = Ipv4Packet::new(ethernet.payload());
if let Some(header) = header {
match header.get_next_level_protocol() {
IpNextHeaderProtocols::Tcp => {
let tcp = TcpPacket::new(header.payload());
if let Some(tcp) = tcp {
//消息从哪块发送到哪块
println!("Tcp packet {}:{} to {}:{}", header.get_source(), tcp.get_source(), header.get_destination(), tcp.get_destination());
}
}
_ => println!("ignore"),
}
}
}
_ => println!("ignore"),
}
}

4 dns

依赖库:
trust-dns-resolver = “0.11.0”
trust-dns = “0.16.0”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
use std::env;
use trust_dns_resolver::Resolver;
use trust_dns_resolver::config::*;
use trust_dns::rr::record_type::RecordType;

fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
eprintln!("Please provide a name to query!");
std::process::exit(1);
}
let query = format!("{}.", args[1]);
//默认方式配置解析器
println!("use default:");
let resolver = Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap();
let response = resolver.lookup_ip(query.as_str());
for ans in response.iter() {
println!("{:?}", ans);
}

//从系统文件配置解析器
println!(" ");
println!("use system:");
let resolver = Resolver::from_system_conf().unwrap();
let response = resolver.lookup_ip(query.as_str());
for ans in response.iter() {
println!("{:?}", ans);
}

println!(" ");
println!("use ns:");
let ns = resolver.lookup(query.as_str(),RecordType::NS);
for ans in response.iter() {
println!("{:?}", ans);
}
}

5. serde

serde crate 是 Serde 生态的核心。
serde_derive crate 提供必要的工具,
使用过程宏来派生 Serialize 和 Deserialize。
但是serde只提供序列化和反序列化的框架,具体的操作还需要依赖具体的包:如serde_json和serde_yaml等。

5.1 基本使用

依赖:
serde = { version = “1.0.106”, features = [“derive”] }
serde_json = “1.0”
serde_yaml = “0.8”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
use serde::{Serialize,Deserialize};

#[derive(Debug,Serialize,Deserialize)]
struct ServerConfig{
workers:u64,
ignore:bool,
auth_server:Option<String>,
}

fn main() {
let config = ServerConfig{
workers:100,
ignore:false,
auth_server:Some("auth.server.io".to_string())
};
{
println!("json:");
let serialized = serde_json::to_string(&config).unwrap();
println!("serialized:{}",serialized);

let deserialized: ServerConfig = serde_json::from_str(&serialized).unwrap();
println!("deserialized: {:#?}",deserialized);
}

{
println!("yaml:");
let serialized = serde_yaml::to_string(&config).unwrap();
println!("serialized:{}",serialized);

let deserialized: ServerConfig = serde_yaml::from_str(&serialized).unwrap();
println!("deserialized: {:#?}",deserialized);
}
}

5.2 serde网络编程中的应用

服务器端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use serde::{Deserialize, Serialize};
use serde_json;
use std::io::{self, prelude::*, BufReader, Write};
use std::net::{TcpListener, TcpStream};
use std::{thread,str};

#[derive(Debug,Serialize,Deserialize)]
struct Point3D {
x: u32,
y: u32,
z: u32,
}

fn handle_client(stream:TcpStream)->io::Result<()>{
println!("Incoming connection from: {}",stream.peer_addr()?);
let mut data = Vec::new();
let mut stream = BufReader::new(stream);
loop{
data.clear();
let bytes_read = stream.read_until(b'\n',&mut data)?;
if bytes_read==0{
return Ok(());
}
let input:Point3D = serde_json::from_slice(&data)?;
let value = input.x.pow(2)+input.y.pow(2)+input.z.pow(2);
stream.get_mut().write(&(serde_json::to_vec(&(f64::from(value).sqrt()))?))?;
stream.get_mut().write(&("\n".as_bytes()))?;
stream.get_mut().flush()?;
}
}

fn main() ->std::io::Result<()>{
let listener = TcpListener::bind("0.0.0.0:8080")?;
for stream in listener.incoming(){
match stream{
Err(e) => eprintln!("error: {}",e),
Ok(stream)=>{
thread::spawn(move ||{
handle_client(stream).unwrap_or_else(|error|eprintln!("error:{}",error));
});
}
}
}
Ok(())
}

客户端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
use serde::{Deserialize, Serialize};
use serde_json;
use std::io::{self, prelude::*, BufReader, Write};
use std::net::{TcpStream};
use std::{str};

#[derive(Debug, Serialize, Deserialize)]
struct Point3D {
x: u32,
y: u32,
z: u32,
}

fn main() -> std::io::Result<()> {
let mut stream = TcpStream::connect("127.0.0.1:8080")?;
loop {

//写数据给服务器端
let mut input = String::new();
let mut buffer: Vec<u8> = Vec::new();
io::stdin().read_line(&mut input).expect("Failed to read from stdin");
let parts: Vec<&str> = input.trim_matches('\n').split(',').collect();
let point = Point3D {
x: parts[0].parse().unwrap(),
y: parts[1].parse().unwrap(),
z: parts[2].parse().unwrap(),
};
stream.write_all(serde_json::to_string(&point).unwrap().as_bytes()).expect("Failed to write");
stream.write_all(b"\n")?; //已传递给服务器端

//从服务器端读数据
let mut reader = BufReader::new(&stream);
reader.read_until(b'\n', &mut buffer)?;
let input = str::from_utf8(&buffer).unwrap();
if input == "" {
eprintln!("Empty response");
}
println!("Respnse:{}", input);
}
}

总结

本文编辑完毕

  • Copyrights © 2017-2023 Jason
  • Visitors: | Views:

谢谢打赏~

微信