pub struct TcpStream { /* 私有字段 */ }展开描述
本地套接字和远程套接字之间的 TCP 流。
TCP 流可以通过 connect 方法连接到端点来创建,也可以通过 接受来自 监听器 的连接来创建。也可以通过 TcpSocket 类型创建 TCP 流。
对 TcpStream 的读写通常使用 AsyncReadExt 和 AsyncWriteExt trait 上的便捷方法来完成。
§示例
use tokio::net::TcpStream;
use tokio::io::AsyncWriteExt;
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Connect to a peer
let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
// Write some data.
stream.write_all(b"hello world!").await?;
Ok(())
}write_all 方法定义在 AsyncWriteExt trait 上。
要在写入方向关闭流,可以调用 shutdown() 方法。这将导致对等方收到长度为 0 的读取,表示不会再发送更多数据。这只会单向关闭流。
实现§
源代码§impl TcpStream
impl TcpStream
源代码pub async fn connect<A: ToSocketAddrs>(addr: A) -> Result<TcpStream>
pub async fn connect<A: ToSocketAddrs>(addr: A) -> Result<TcpStream>
打开到远程主机的 TCP 连接。
addr 是远程主机的地址。任何实现了 ToSocketAddrs trait 的类型都可以作为地址提供。如果 addr 产生多个地址,则会依次尝试与每个地址进行连接,直到连接成功。如果没有任何地址导致成功连接,则返回最后一次连接尝试(最后一个地址)的错误。
要在连接之前配置套接字,可以使用 TcpSocket 类型。
§示例
use tokio::net::TcpStream;
use tokio::io::AsyncWriteExt;
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Connect to a peer
let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
// Write some data.
stream.write_all(b"hello world!").await?;
Ok(())
}write_all 方法定义在 AsyncWriteExt trait 上。
源代码pub fn from_std(stream: TcpStream) -> Result<TcpStream>
pub fn from_std(stream: TcpStream) -> Result<TcpStream>
从 std::net::TcpStream 创建一个新的 TcpStream。
此函数旨在用于将标准库的 TCP 流包装为 Tokio 等价物。
§注意
调用者负责确保流处于非阻塞模式。否则,对流的所有 I/O 操作都会阻塞线程,从而导致意外行为。可以使用 set_nonblocking 设置非阻塞模式。
在阻塞模式下传入监听器始终是错误的,这种情况下行为将来可能会发生变化。例如,可能会发生 panic。
§示例
use std::error::Error;
use tokio::net::TcpStream;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let std_stream = std::net::TcpStream::connect("127.0.0.1:34254")?;
std_stream.set_nonblocking(true)?;
let stream = TcpStream::from_std(std_stream)?;
Ok(())
}§恐慌
如果不在已启用 I/O 的运行时中调用,此函数会发生 panic。
当从由 tokio 运行时驱动的 future 中调用此函数时,运行时通常是隐式设置的;否则可以通过 Runtime::enter 函数显式设置运行时。
源代码pub fn into_std(self) -> Result<TcpStream>
pub fn into_std(self) -> Result<TcpStream>
将 tokio::net::TcpStream 转换为 std::net::TcpStream。
返回的 std::net::TcpStream 将 nonblocking 模式设置为 true。如果需要,使用 set_nonblocking 更改阻塞模式。
§示例
use std::error::Error;
use std::io::Read;
use tokio::net::TcpListener;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let mut data = [0u8; 12];
let listener = TcpListener::bind("127.0.0.1:34254").await?;
let (tokio_tcp_stream, _) = listener.accept().await?;
let mut std_tcp_stream = tokio_tcp_stream.into_std()?;
std_tcp_stream.set_nonblocking(false)?;
std_tcp_stream.read_exact(&mut data)?;
Ok(())
}源代码pub fn local_addr(&self) -> Result<SocketAddr>
pub fn local_addr(&self) -> Result<SocketAddr>
返回此流绑定的本地地址。
§示例
use tokio::net::TcpStream;
let stream = TcpStream::connect("127.0.0.1:8080").await?;
println!("{:?}", stream.local_addr()?);源代码pub fn take_error(&self) -> Result<Option<Error>>
pub fn take_error(&self) -> Result<Option<Error>>
返回 SO_ERROR 选项的值。
源代码pub fn peer_addr(&self) -> Result<SocketAddr>
pub fn peer_addr(&self) -> Result<SocketAddr>
返回此流连接到的远程地址。
§示例
use tokio::net::TcpStream;
let stream = TcpStream::connect("127.0.0.1:8080").await?;
println!("{:?}", stream.peer_addr()?);源代码pub fn poll_peek(
&self,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<Result<usize>>
pub fn poll_peek( &self, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll<Result<usize>>
尝试在套接字上接收数据,但不会从队列中移除该数据。如果数据尚未可用,则注册当前任务以接收唤醒。
请注意,在多次调用 poll_peek、poll_read 或 poll_read_ready 时,只有传递给最近一次调用的 Context 中的 Waker 会被调度接收唤醒。(但是,poll_write 保留了一个独立的第二个 waker。)
§返回值
函数返回:
Poll::Pendingif data is not yet available.Poll::Ready(Ok(n))if data is available.nis the number of bytes peeked.Poll::Ready(Err(e))if an error is encountered.
§错误
此函数可能遇到除 WouldBlock 之外的任何标准 I/O 错误。
§示例
use tokio::io::{self, ReadBuf};
use tokio::net::TcpStream;
use std::future::poll_fn;
#[tokio::main]
async fn main() -> io::Result<()> {
let stream = TcpStream::connect("127.0.0.1:8000").await?;
let mut buf = [0; 10];
let mut buf = ReadBuf::new(&mut buf);
poll_fn(|cx| {
stream.poll_peek(cx, &mut buf)
}).await?;
Ok(())
}源代码pub async fn ready(&self, interest: Interest) -> Result<Ready>
pub async fn ready(&self, interest: Interest) -> Result<Ready>
等待任何所请求的就绪状态。
此函数通常与 try_read() 或 try_write() 配对使用。它可用于在单个任务上同时对同一套接字进行读/写,而无需拆分套接字。
该函数可能在套接字尚未就绪时完成。这是一种误报,尝试进行操作将返回 io::ErrorKind::WouldBlock。该函数也可能返回空的 Ready 集合,因此应始终检查返回值,如果请求的状态未设置,可能需要再次等待。
§取消安全性
此方法可安全取消。一旦就绪事件发生,该方法将继续立即返回,直到通过尝试读取或写入而消费该就绪事件(失败时返回 WouldBlock 或 Poll::Pending)。
§示例
在单个任务上同时对流进行读写,而无需拆分。
use tokio::io::Interest;
use tokio::net::TcpStream;
use std::error::Error;
use std::io;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let stream = TcpStream::connect("127.0.0.1:8080").await?;
loop {
let ready = stream.ready(Interest::READABLE | Interest::WRITABLE).await?;
if ready.is_readable() {
let mut data = vec![0; 1024];
// 尝试读取数据,这仍可能因 `WouldBlock` 而失败
// 如果就绪事件是误报。
match stream.try_read(&mut data) {
Ok(n) => {
println!("read {} bytes", n);
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
if ready.is_writable() {
// 尝试写入数据,这仍可能因 `WouldBlock` 而失败
// 如果就绪事件是误报。
match stream.try_write(b"hello world") {
Ok(n) => {
println!("write {} bytes", n);
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue
}
Err(e) => {
return Err(e.into());
}
}
}
}
}源代码pub async fn readable(&self) -> Result<()>
pub async fn readable(&self) -> Result<()>
等待套接字变为可读。
此函数等价于 ready(Interest::READABLE),通常与 try_read() 配对使用。
§取消安全性
此方法可安全取消。一旦就绪事件发生,该方法将继续立即返回,直到通过尝试读取而消费该就绪事件(失败时返回 WouldBlock 或 Poll::Pending)。
§示例
use tokio::net::TcpStream;
use std::error::Error;
use std::io;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Connect to a peer
let stream = TcpStream::connect("127.0.0.1:8080").await?;
let mut msg = vec![0; 1024];
loop {
// Wait for the socket to be readable
stream.readable().await?;
// Try to read data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match stream.try_read(&mut msg) {
Ok(n) => {
msg.truncate(n);
break;
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
println!("GOT = {:?}", msg);
Ok(())
}源代码pub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
pub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
轮询读就绪状态。
如果 tcp 流当前尚未准备好读取,此方法将存储从所提供 Context 克隆的 Waker。当 tcp 流准备好读取时,将在该 waker 上调用 Waker::wake。
请注意,在多次调用 poll_read_ready、poll_read 或 poll_peek 时,只有传递给最近一次调用的 Context 中的 Waker 会被调度接收唤醒。(但是,poll_write_ready 保留了一个独立的第二个 waker。)
此函数用于通过 readable 创建并固定 future 不可行的情况。在可能的情况下,首选使用 readable,因为它支持一次从多个任务进行轮询。
§返回值
函数返回:
Poll::Pendingif the tcp stream is not ready for reading.Poll::Ready(Ok(()))if the tcp stream is ready for reading.Poll::Ready(Err(e))if an error is encountered.
§错误
此函数可能遇到除 WouldBlock 之外的任何标准 I/O 错误。
源代码pub fn try_read(&self, buf: &mut [u8]) -> Result<usize>
pub fn try_read(&self, buf: &mut [u8]) -> Result<usize>
尝试从流中读取数据到提供的缓冲区,返回读取的字节数。
接收套接字上任何待处理的数据,但不会等待新数据到达。成功时返回读取的字节数。由于 try_read() 是非阻塞的,缓冲区不必由异步任务存储,可以完全存在于栈上。
通常,readable() 或 ready() 与此函数配对使用。
§返回值
如果成功读取数据,则返回 Ok(n),其中 n 是读取的字节数。如果 n 为 0,则可能表示以下两种情况之一:
- The stream’s read half is closed and will no longer yield data.
- The specified buffer was 0 bytes in length.
如果流未准备好读取数据,则返回 Err(io::ErrorKind::WouldBlock)。
§示例
use tokio::net::TcpStream;
use std::error::Error;
use std::io;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Connect to a peer
let stream = TcpStream::connect("127.0.0.1:8080").await?;
loop {
// Wait for the socket to be readable
stream.readable().await?;
// Creating the buffer **after** the `await` prevents it from
// being stored in the async task.
let mut buf = [0; 4096];
// Try to read data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match stream.try_read(&mut buf) {
Ok(0) => break,
Ok(n) => {
println!("read {} bytes", n);
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
Ok(())
}源代码pub fn try_read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
pub fn try_read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
尝试从流中读取数据到提供的多个缓冲区,返回读取的字节数。
数据按顺序被复制以填充每个缓冲区,最后一个写入的缓冲区可能仅部分填充。此方法的行为等效于使用连接缓冲区对 try_read() 进行单次调用。
接收套接字上任何待处理的数据,但不会等待新数据到达。成功时返回读取的字节数。由于 try_read_vectored() 是非阻塞的,缓冲区不必由异步任务存储,可以完全存在于栈上。
通常,readable() 或 ready() 与此函数配对使用。
§返回值
如果成功读取数据,则返回 Ok(n),其中 n 是读取的字节数。Ok(0) 表示流的读半部分已关闭,将不再产生数据。如果流未准备好读取数据,则返回 Err(io::ErrorKind::WouldBlock)。
§示例
use tokio::net::TcpStream;
use std::error::Error;
use std::io::{self, IoSliceMut};
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Connect to a peer
let stream = TcpStream::connect("127.0.0.1:8080").await?;
loop {
// Wait for the socket to be readable
stream.readable().await?;
// Creating the buffer **after** the `await` prevents it from
// being stored in the async task.
let mut buf_a = [0; 512];
let mut buf_b = [0; 1024];
let mut bufs = [
IoSliceMut::new(&mut buf_a),
IoSliceMut::new(&mut buf_b),
];
// Try to read data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match stream.try_read_vectored(&mut bufs) {
Ok(0) => break,
Ok(n) => {
println!("read {} bytes", n);
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
Ok(())
}源代码pub async fn writable(&self) -> Result<()>
pub async fn writable(&self) -> Result<()>
等待套接字变为可写。
此函数等价于 ready(Interest::WRITABLE),通常与 try_write() 配对使用。
§取消安全性
此方法可安全取消。一旦就绪事件发生,该方法将继续立即返回,直到通过尝试写入而消费该就绪事件(失败时返回 WouldBlock 或 Poll::Pending)。
§示例
use tokio::net::TcpStream;
use std::error::Error;
use std::io;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Connect to a peer
let stream = TcpStream::connect("127.0.0.1:8080").await?;
loop {
// Wait for the socket to be writable
stream.writable().await?;
// Try to write data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match stream.try_write(b"hello world") {
Ok(n) => {
break;
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
Ok(())
}源代码pub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
pub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
轮询写就绪状态。
如果 tcp 流当前尚未准备好写入,此方法将存储从所提供 Context 克隆的 Waker。当 tcp 流准备好写入时,将在该 waker 上调用 Waker::wake。
请注意,在多次调用 poll_write_ready 或 poll_write 时,只有传递给最近一次调用的 Context 中的 Waker 会被调度以接收唤醒。(但是,poll_read_ready 保留了一个独立的第二个唤醒器。)
此函数用于通过 writable 创建并固定 future 不可行的情况。在可能的情况下,首选使用 writable,因为它支持一次从多个任务进行轮询。
§返回值
函数返回:
Poll::Pendingif the tcp stream is not ready for writing.Poll::Ready(Ok(()))if the tcp stream is ready for writing.Poll::Ready(Err(e))if an error is encountered.
§错误
此函数可能遇到除 WouldBlock 之外的任何标准 I/O 错误。
源代码pub fn try_write(&self, buf: &[u8]) -> Result<usize>
pub fn try_write(&self, buf: &[u8]) -> Result<usize>
尝试将缓冲区写入流,返回已写入的字节数。
该函数将尝试写入 buf 的全部内容,但缓冲区可能只有部分被写入。
此函数通常与 writable() 配对使用。
§返回值
如果成功写入数据,则返回 Ok(n),其中 n 是写入的字节数。如果流未准备好写入数据,则返回 Err(io::ErrorKind::WouldBlock)。
§示例
use tokio::net::TcpStream;
use std::error::Error;
use std::io;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Connect to a peer
let stream = TcpStream::connect("127.0.0.1:8080").await?;
loop {
// Wait for the socket to be writable
stream.writable().await?;
// Try to write data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match stream.try_write(b"hello world") {
Ok(n) => {
break;
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
Ok(())
}源代码pub fn try_write_vectored(&self, bufs: &[IoSlice<'_>]) -> Result<usize>
pub fn try_write_vectored(&self, bufs: &[IoSlice<'_>]) -> Result<usize>
尝试将多个缓冲区写入流,返回写入的字节数。
数据按顺序从每个缓冲区写入,最后读取的缓冲区可能仅被部分消费。此方法的行为等效于使用连接缓冲区对 try_write() 进行单次调用。
此函数通常与 writable() 配对使用。
§返回值
如果成功写入数据,则返回 Ok(n),其中 n 是写入的字节数。如果流未准备好写入数据,则返回 Err(io::ErrorKind::WouldBlock)。
§示例
use tokio::net::TcpStream;
use std::error::Error;
use std::io;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Connect to a peer
let stream = TcpStream::connect("127.0.0.1:8080").await?;
let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")];
loop {
// Wait for the socket to be writable
stream.writable().await?;
// Try to write data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match stream.try_write_vectored(&bufs) {
Ok(n) => {
break;
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue;
}
Err(e) => {
return Err(e.into());
}
}
}
Ok(())
}源代码pub fn try_io<R>(
&self,
interest: Interest,
f: impl FnOnce() -> Result<R>,
) -> Result<R>
pub fn try_io<R>( &self, interest: Interest, f: impl FnOnce() -> Result<R>, ) -> Result<R>
尝试使用用户提供的 I/O 操作从套接字读取或写入数据。
如果套接字已就绪,则调用提供的闭包。闭包应通过手动调用适当的系统调用来尝试在套接字上执行 I/O 操作。如果操作失败的原因是套接字实际上尚未就绪,则闭包应返回 WouldBlock 错误,同时会清除就绪标志。闭包的返回值随后由 try_io 返回。
如果套接字未就绪,则不会调用闭包,并返回 WouldBlock 错误。
闭包仅在已对套接字执行了 I/O 操作且因套接字未就绪而失败时,才应返回 WouldBlock 错误。在其他任何情况下返回 WouldBlock 错误都会错误地清除就绪标志,可能导致套接字行为异常。
闭包不应使用 Tokio TcpStream 类型上定义的任何方法来执行 I/O 操作,因为这会干扰就绪标志,并可能导致套接字行为异常。
此方法不应用于组合的就绪事件。闭包应当只执行一种 I/O 操作,因此不应需要多于一个的就绪状态。如果以组合的就绪事件调用,此方法可能会发生 panic 或永久休眠。
通常,readable()、writable() 或 ready() 与此函数一起使用。
源代码pub async fn async_io<R>(
&self,
interest: Interest,
f: impl FnMut() -> Result<R>,
) -> Result<R>
pub async fn async_io<R>( &self, interest: Interest, f: impl FnMut() -> Result<R>, ) -> Result<R>
使用用户提供的 I/O 操作从套接字读取或写入数据。
会等待套接字的就绪状态,当套接字就绪时,会调用提供的闭包。闭包应通过手动调用适当的系统调用来尝试在套接字上执行 I/O 操作。如果操作失败的原因是套接字实际上尚未就绪,则闭包应返回 WouldBlock 错误。在这种情况下,会清除就绪标志并重新等待套接字就绪。该循环将一直重复,直到闭包返回 Ok 或除 WouldBlock 之外的错误。
闭包仅在已对套接字执行了 I/O 操作且因套接字未就绪而失败时,才应返回 WouldBlock 错误。在其他任何情况下返回 WouldBlock 错误都会错误地清除就绪标志,可能导致套接字行为异常。
闭包不应使用 Tokio TcpStream 类型上定义的任何方法来执行 I/O 操作,因为这会干扰就绪标志,并可能导致套接字行为异常。
此方法不应用于组合的就绪事件。闭包应当只执行一种 I/O 操作,因此不应需要多于一个的就绪状态。如果以组合的就绪事件调用,此方法可能会发生 panic 或永久休眠。
源代码pub async fn peek(&self, buf: &mut [u8]) -> Result<usize>
pub async fn peek(&self, buf: &mut [u8]) -> Result<usize>
在套接字上从其连接的远程地址接收数据,但不会从队列中移除该数据。成功时返回窥视到的字节数。
连续调用将返回相同的数据。这是通过将 MSG_PEEK 作为标志传递给底层 recv 系统调用来实现的。
§取消安全性
此方法是可安全取消的。如果在 tokio::select! 语句中将此方法用作事件,并且其他某个分支先完成,那么可以保证未执行任何 peek 操作,并且 buf 未经修改。
§示例
use tokio::net::TcpStream;
use tokio::io::AsyncReadExt;
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Connect to a peer
let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
let mut b1 = [0; 10];
let mut b2 = [0; 10];
// Peek at the data
let n = stream.peek(&mut b1).await?;
// Read the data
assert_eq!(n, stream.read(&mut b2[..n]).await?);
assert_eq!(&b1[..n], &b2[..n]);
Ok(())
}read 方法定义在 AsyncReadExt trait 上。
源代码pub fn nodelay(&self) -> Result<bool>
pub fn nodelay(&self) -> Result<bool>
获取此套接字上 TCP_NODELAY 选项的值。
有关此选项的更多信息,请参阅 set_nodelay。
§示例
use tokio::net::TcpStream;
let stream = TcpStream::connect("127.0.0.1:8080").await?;
println!("{:?}", stream.nodelay()?);源代码pub fn set_nodelay(&self, nodelay: bool) -> Result<()>
pub fn set_nodelay(&self, nodelay: bool) -> Result<()>
设置此套接字上 TCP_NODELAY 选项的值。
如果设置,则此选项禁用 Nagle 算法。这意味着段会尽快发送,即使只有少量数据。当未设置时,数据会被缓冲,直到有足够的数据量再发送,从而避免频繁发送小数据包。
§示例
use tokio::net::TcpStream;
let stream = TcpStream::connect("127.0.0.1:8080").await?;
stream.set_nodelay(true)?;源代码pub fn linger(&self) -> Result<Option<Duration>>
pub fn linger(&self) -> Result<Option<Duration>>
通过获取 SO_LINGER 选项来读取此套接字的 linger 时长。
有关此选项的更多信息,请参阅 set_zero_linger 和 set_linger。
§示例
use tokio::net::TcpStream;
let stream = TcpStream::connect("127.0.0.1:8080").await?;
println!("{:?}", stream.linger()?);源代码pub fn set_linger(&self, dur: Option<Duration>) -> Result<()>
👎Deprecated: SO_LINGER causes the socket to block the thread on drop
pub fn set_linger(&self, dur: Option<Duration>) -> Result<()>
SO_LINGER causes the socket to block the thread on drop通过设置 SO_LINGER 选项来设置此套接字的 linger 时长。
此选项控制当流存在未发送消息且流已关闭时所采取的动作。如果设置了 SO_LINGER,系统将阻塞进程,直到能够传输数据或时间到期。
如果未指定 SO_LINGER,并且流已关闭,系统会以允许进程尽快继续的方式处理此调用。
此选项已被弃用,因为在 Tokio 中使用的套接字上设置 SO_LINGER 始终是错误的,这会导致在套接字关闭时阻塞线程。有关更多详细信息,请参阅:
关于
SO_LINGER与非阻塞 (O_NONBLOCK) 套接字之间的复杂性,已有大量通信文献加以讨论。据我所知,最终结论是:不要这样做。而是依赖于shutdown()后接read()获得 EOF 的技术。
尽管此方法已弃用,但它不会从 Tokio 中移除。
请注意,将 SO_LINGER 设为零的特殊情况不会导致阻塞。Tokio 为此提供了 set_zero_linger。
§示例
use tokio::net::TcpStream;
let stream = TcpStream::connect("127.0.0.1:8080").await?;
stream.set_linger(None)?;源代码pub fn set_zero_linger(&self) -> Result<()>
pub fn set_zero_linger(&self) -> Result<()>
通过设置 SO_LINGER 选项将此套接字的 linger 时长设置为零。
这将导致在套接字被 drop 或关闭时强制中止连接(“abortive close”)。正常的 TCP 关闭握手(FIN/ACK)将不再发生,而是会向对等方发送一个 TCP RST(重置)段,并且套接字会立即丢弃驻留在套接字发送缓冲区中的任何未发送数据。这可以防止套接字在关闭后进入 TIME_WAIT 状态。
这是一个破坏性操作。操作系统当前已缓冲但尚未传输的任何数据都将丢失。对等方很可能会收到一个 “Connection Reset” 错误,而不是干净的流结束。
有关 SO_LINGER 工作原理的更多详细信息,请参阅 set_linger 的文档。
§示例
use std::time::Duration;
use tokio::net::TcpStream;
let stream = TcpStream::connect("127.0.0.1:8080").await?;
stream.set_zero_linger()?;
assert_eq!(stream.linger()?, Some(Duration::ZERO));源代码pub fn set_ttl(&self, ttl: u32) -> Result<()>
pub fn set_ttl(&self, ttl: u32) -> Result<()>
设置此套接字上 IP_TTL 选项的值。
此值设置从此套接字发送的每个数据包中使用的生存时间字段。
§示例
use tokio::net::TcpStream;
let stream = TcpStream::connect("127.0.0.1:8080").await?;
stream.set_ttl(123)?;源代码pub fn split<'a>(&'a mut self) -> (ReadHalf<'a>, WriteHalf<'a>)
pub fn split<'a>(&'a mut self) -> (ReadHalf<'a>, WriteHalf<'a>)
将 TcpStream 拆分为读半部分和写半部分,可用于并发地读写流。
此方法比 into_split 更高效,但拆分出的两半不能移动到独立生成的任务中。
源代码pub fn into_split(self) -> (OwnedReadHalf, OwnedWriteHalf)
pub fn into_split(self) -> (OwnedReadHalf, OwnedWriteHalf)
将 TcpStream 拆分为读半部分和写半部分,可用于并发地读写流。
与 split 不同,拥有的两半可以移动到单独的任务中,但这是以堆分配为代价的。
注意: drop 写半部将关闭 TCP 流的写半部。这等效于在 TcpStream 上调用 shutdown()。
trait 实现§
源代码§impl AsRawSocket for TcpStream
Available on docsrs, or Windows only.
impl AsRawSocket for TcpStream
docsrs, or Windows only.源代码§fn as_raw_socket(&self) -> RawSocket
fn as_raw_socket(&self) -> RawSocket
源代码§impl AsRef<TcpStream> for OwnedReadHalf
impl AsRef<TcpStream> for OwnedReadHalf
源代码§impl AsRef<TcpStream> for OwnedWriteHalf
impl AsRef<TcpStream> for OwnedWriteHalf
源代码§impl AsSocket for TcpStream
Available on docsrs, or Windows only.
impl AsSocket for TcpStream
docsrs, or Windows only.源代码§fn as_socket(&self) -> BorrowedSocket<'_>
fn as_socket(&self) -> BorrowedSocket<'_>
源代码§impl AsyncWrite for TcpStream
impl AsyncWrite for TcpStream
源代码§fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize>>
fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<Result<usize>>
buf into the object. 更多信息源代码§fn poll_write_vectored(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[IoSlice<'_>],
) -> Poll<Result<usize>>
fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll<Result<usize>>
poll_write, except that it writes from a slice of buffers. 更多信息源代码§fn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
poll_write_vectored
implementation. 更多信息