该模块包含TCP/UDP/Unix网络类型,类似于标准库,可用于实现网络协议。
networking protocols
TcpListener and TcpStream provide functionality for communication over TCP
UdpSocket provides functionality for communication over UDP
UnixListener and UnixStream provide functionality for communication over a Unix Domain Stream Socket (available on Unix only)
UnixDatagram provides functionality for communication over Unix Domain Datagram Socket (available on Unix only)
tcp TCP utility types, TCP 实用程序类型
unix Unix specific network types, 基于Unix的网络类型
pub struct TcpSocket {
/* private fields */ }
还未转换为TcpStream或TcpListener的socket
封装了OS套接字,并在建立TCP连接之前(C端)/接收入流量之前(S端),配置套接字
Rust 的 TcpSocket 类型是基于 RAII(Resource Acquisition Is Initialization)语法设计。它在创建时会获取系统资源(即打开一个 TCP 套接字),并在其生命周期结束时自动释放该资源(即关闭套接字)。
这种设计方式在 Rust 中通常被称为 “资源句柄”,在 C++ 和其他语言中也称为 “智能指针”。
当 TcpSocket 的值被丢弃时,它所持有的套接字将被自动关闭。
这种机制确保资源正确释放,避免像 “内存泄漏” 或 “文件句柄泄漏” 等问题。
TcpStream::connect("127.0.0.1:8080")
等价于
use tokio::net::TcpSocket;
use std::io;
#[tokio::main]
async fn main() -> io::Result<()> {
let addr = "127.0.0.1:8080".parse().unwrap();
let socket = TcpSocket::new_v4()?;
let stream = socket.connect(addr).await?;
Ok(())
}
TcpListener::bind("127.0.0.1:8080")
等价于
use tokio::net::TcpSocket;
use std::io;
#[tokio::main]
async fn main() -> io::Result<()> {
// 使用 parse() 方法将字符串解析为 SocketAddr 类型的值
// 使用 unwrap() 方法处理可能发生的错误
// 使用 unwrap() 方法处理错误可能会导致程序 panic,需要用其他错误处理机制
let addr = "127.0.0.1:8080".parse().unwrap();
let socket = TcpSocket::new_v4()?;
// On platforms with Berkeley-derived sockets, this allows to quickly
// rebind a socket, without needing to wait for the OS to clean up the
// previous one.
//
// On Windows, this allows rebinding sockets which are actively in use,
// which allows “socket hijacking”, so we explicitly don't set it here.
// https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
// 地址重用
socket.set_reuseaddr(true)?;
socket.bind(addr)?;
let listener = socket.listen(1024)?;
Ok(())
}
TcpSocket 类型本身仅提供了一些基本的套接字选项,例如设置超时等。
如果需要设置其他的套接字选项,如设置 SO_SNDBUF 或 SO_RCVBUF 缓冲区大小等,可以使用 RawFd 或 RawSocket 类型,通过 std::os::unix::io::AsRawFd 或 std::os::windows::io::AsRawSocket 方法获取原始文件描述符或原始套接字句柄,并结合 socket2 crate 等三方 crate 来设置所需的选项。
获取socket的IP_TOS option
在计算机网络中,IP_TOS 是一种 IP 数据报头中的字段,用于指定 IP 数据报的优先级和特殊处理。TOS 是 Type of Service(服务类型)的缩写,该字段已被新的 DSCP(Differentiated Services Code Point,差异化服务代码点)替换,DSCP 可以更好地实现服务质量(QoS)。
IP_TOS 的高 3 位被称为 IP 优先级,低 5 位被称为 IP 服务类型。
IP 优先级可以分为以下几个类别:
IP 服务类型可以分为以下几个类别:
在 IP 数据报头的 TOS 字段中,这些值可以通过位运算进行组合使用,从而实现具有不同优先级和服务类型的 IP 数据报的传输。例如,可以将高于 Routine 优先级的包发送到专用的信道,这些信道在网络流量规划中优先处理,以实现更快的传输速度和更高的可靠性。
std::net::TcpStream 转为 TcpSocket
The provided socket must not have been connected prior to calling this function
调用该函数前,提供的socket不能处于连接状态
typically used together with crates such as socket2 to configure socket options that are not available on TcpSocket.
通常和socket2一起使用,来配置socket选项,因为TcpSocket提供的功能有限
use tokio::net::TcpSocket;
use socket2::{
Domain, Socket, Type};
#[tokio::main]
async fn main() -> std::io::Result<()> {
let socket2_socket = Socket::new(Domain::IPV4, Type::STREAM, None)?;
socket2_socket.set_nonblocking(true)?;
let socket = TcpSocket::from_std_stream(socket2_socket.into