pub struct TcpStream { /* private fields */ }展开描述
本地套接字与远端套接字之间的 TCP 流。
可以通过调用 connect 方法连接到某个端点,或者通过 接受来自监听器 的连接来创建 TCP 流。也可以通过 TcpSocket 类型来创建。
对 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 的内容,表明不会再发送更多数据。该操作仅关闭流的一个方向。
实现§
Source§impl TcpStream
impl TcpStream
Sourcepub 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 上。
Sourcepub fn from_std(stream: TcpStream) -> Result<TcpStream>
pub fn from_std(stream: TcpStream) -> Result<TcpStream>
从 std::net::TcpStream 创建新的 TcpStream。
该函数用于将标准库中的 TCP 流包装为 Tokio 的对应类型。
§Notes
调用者负责确保流处于非阻塞模式。否则,流上的所有 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(())
}§Panics
如果该函数不是在启用了 IO 的运行时中调用,则会引发 panic。
运行时通常会在从由 tokio 运行时驱动的 future 中调用此函数时隐式设置,否则可以使用 Runtime::enter 函数显式设置。
Sourcepub fn into_std(self) -> Result<TcpStream>
pub fn into_std(self) -> Result<TcpStream>
将 tokio::net::TcpStream 转换为 std::net::TcpStream。
返回的 std::net::TcpStream 的非阻塞模式将被设置为 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(())
}Sourcepub 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()?);Sourcepub fn take_error(&self) -> Result<Option<Error>>
pub fn take_error(&self) -> Result<Option<Error>>
返回 SO_ERROR 选项的值。
Sourcepub 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()?);Sourcepub 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。)
§Return value
函数返回:
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.
§Errors
该函数可能会遇到除 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(())
}Sourcepub 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 集合,因此应始终检查返回值,若请求的状态尚未设置则可能需要再次等待。
§Cancel safety
此方法可安全取消。一旦就绪事件发生,该方法将持续立即返回,直到就绪事件被尝试进行读取或写入(且失败返回 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];
// Try to read data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
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() {
// 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) => {
println!("write {} bytes", n);
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
continue
}
Err(e) => {
return Err(e.into());
}
}
}
}
}Sourcepub async fn readable(&self) -> Result<()>
pub async fn readable(&self) -> Result<()>
等待套接字变为可读。
该函数等同于 ready(Interest::READABLE),通常与 try_read() 配合使用。
§Cancel safety
此方法可安全取消。一旦就绪事件发生,该方法将持续立即返回,直到就绪事件被尝试进行读取(且失败返回 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(())
}Sourcepub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
pub fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
Poll 读取就绪状态。
如果 tcp 流当前尚未准备好读取,此方法会存储提供的 Context 中 Waker 的一个克隆。当 tcp 流变为可读时,会在该 waker 上调用 Waker::wake。
请注意,对于 poll_read_ready、poll_read 或 poll_peek 的多次调用,仅会调度传递给最近一次调用的 Context 中的 Waker 接收唤醒。(不过,poll_write_ready 仍保留一个独立的 waker。)
该函数用于不便通过 readable 创建并固定一个 future 的场景。在条件允许时,建议使用 readable,因为它支持同时从多个任务进行 poll。
§Return value
函数返回:
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.
§Errors
该函数可能会遇到除 WouldBlock 之外的任何标准 I/O 错误。
Sourcepub fn try_read(&self, buf: &mut [u8]) -> Result<usize>
pub fn try_read(&self, buf: &mut [u8]) -> Result<usize>
尝试从流读取数据到所提供的缓冲区中,返回读取的字节数。
从套接字接收任何已有数据,但不会等待新数据的到达。成功时返回已读取的字节数。由于 try_read() 是非阻塞的,缓冲区不必由异步任务持有,可以完全存在于栈上。
通常,readable() 或 ready() 与该函数配合使用。
§Return
如果成功读取数据,则返回 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(())
}Sourcepub 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() 与该函数配合使用。
§Return
如果成功读取数据,则返回 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(())
}Sourcepub fn try_read_buf<B: BufMut>(&self, buf: &mut B) -> Result<usize>
pub fn try_read_buf<B: BufMut>(&self, buf: &mut B) -> Result<usize>
尝试从流读取数据到所提供的缓冲区中,并推进缓冲区的内部游标,返回读取的字节数。
从套接字接收任何已有数据,但不会等待新数据的到达。成功时返回已读取的字节数。由于 try_read_buf() 是非阻塞的,缓冲区不必由异步任务持有,可以完全存在于栈上。
通常,readable() 或 ready() 与该函数配合使用。
§Return
如果成功读取数据,则返回 Ok(n),其中 n 是已读取的字节数。Ok(0) 表示流的读半部已关闭,并且不再产生数据。如果流尚未准备好读取数据,则返回 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?;
let mut buf = Vec::with_capacity(4096);
// Try to read data, this may still fail with `WouldBlock`
// if the readiness event is a false positive.
match stream.try_read_buf(&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(())
}Sourcepub async fn writable(&self) -> Result<()>
pub async fn writable(&self) -> Result<()>
等待套接字变为可写。
该函数等同于 ready(Interest::WRITABLE),通常与 try_write() 配合使用。
§Cancel safety
此方法可安全取消。一旦就绪事件发生,该方法将持续立即返回,直到就绪事件被尝试进行写入(且失败返回 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(())
}Sourcepub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
pub fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<Result<()>>
Poll 写入就绪状态。
如果 tcp 流当前尚未准备好写入,此方法会存储提供的 Context 中 Waker 的一个克隆。当 tcp 流变为可写时,会在该 waker 上调用 Waker::wake。
请注意,对于 poll_write_ready 或 poll_write 的多次调用,仅会调度传递给最近一次调用的 Context 中的 Waker 接收唤醒。(不过,poll_read_ready 仍保留一个独立的 waker。)
该函数用于不便通过 writable 创建并固定一个 future 的场景。在条件允许时,建议使用 writable,因为它支持同时从多个任务进行 poll。
§Return value
函数返回:
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.
§Errors
该函数可能会遇到除 WouldBlock 之外的任何标准 I/O 错误。
Sourcepub fn try_write(&self, buf: &[u8]) -> Result<usize>
pub fn try_write(&self, buf: &[u8]) -> Result<usize>
尝试将缓冲区写入流,返回写入的字节数。
该函数会尝试写入 buf 的全部内容,但可能只会写入缓冲区的一部分。
该函数通常与 writable() 配合使用。
§Return
如果数据成功写入,则返回 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(())
}Sourcepub fn try_write_vectored(&self, bufs: &[IoSlice<'_>]) -> Result<usize>
pub fn try_write_vectored(&self, bufs: &[IoSlice<'_>]) -> Result<usize>
尝试将多个缓冲区写入流,返回写入的字节数。
数据从每个缓冲区依次写入,最后一个缓冲区可能仅被部分消费。此方法等效于对拼接后的缓冲区进行一次 try_write() 调用。
该函数通常与 writable() 配合使用。
§Return
如果数据成功写入,则返回 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(())
}Sourcepub 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>
尝试使用用户提供的 IO 操作对套接字进行读写。
如果套接字就绪,则调用所提供的闭包。闭包应通过手动调用适当的系统调用来尝试对套接字执行 IO 操作。如果由于套接字实际上未就绪而导致操作失败,则闭包应返回 WouldBlock 错误,并清除就绪标志。然后 try_io 返回闭包的返回值。
如果套接字尚未就绪,则不会调用闭包,并返回 WouldBlock 错误。
闭包只有在执行了因套接字未就绪而失败的 IO 操作时,才应返回 WouldBlock 错误。在其他情况下返回 WouldBlock 错误会错误地清除就绪标志,可能导致套接字行为异常。
闭包不应使用 Tokio TcpStream 类型上定义的任何方法来执行 IO 操作,因为这会干扰就绪标志,并可能导致套接字行为异常。
该方法不应与组合的 interest 一起使用。闭包应仅执行一种 IO 操作,因此不应需要多于一个就绪状态。如果使用组合的 interest 调用此方法,它可能会 panic 或永远睡眠。
通常,readable()、writable() 或 ready() 与该函数配合使用。
Sourcepub 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>
使用用户提供的 IO 操作对套接字进行读写。
等待套接字就绪,一旦就绪就调用所提供的闭包。闭包应通过手动调用适当的系统调用来尝试对套接字执行 IO 操作。如果由于套接字实际上未就绪而导致操作失败,则闭包应返回 WouldBlock 错误。此时就绪标志被清除,然后再次等待套接字就绪。该循环会反复进行,直到闭包返回 Ok 或 WouldBlock 以外的错误。
闭包只有在执行了因套接字未就绪而失败的 IO 操作时,才应返回 WouldBlock 错误。在其他情况下返回 WouldBlock 错误会错误地清除就绪标志,可能导致套接字行为异常。
闭包不应使用 Tokio TcpStream 类型上定义的任何方法来执行 IO 操作,因为这会干扰就绪标志,并可能导致套接字行为异常。
该方法不应与组合的 interest 一起使用。闭包应仅执行一种 IO 操作,因此不应需要多于一个就绪状态。如果使用组合的 interest 调用此方法,它可能会 panic 或永远睡眠。
Sourcepub async fn peek(&self, buf: &mut [u8]) -> Result<usize>
pub async fn peek(&self, buf: &mut [u8]) -> Result<usize>
从套接字所连接的远端地址接收数据,但不会从队列中移除该数据。成功时返回已窥视的字节数。
连续调用将返回相同的数据。这是通过将 MSG_PEEK 作为底层 recv 系统调用的标志来实现的。
§Cancel safety
此方法可安全取消。如果该方法作为 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 上。
Sourcepub 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()?);Sourcepub 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)?;Sourcepub 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()?);Sourcepub 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 的技术。来自 The ultimate
SO_LINGERpage, or: why is my tcp not reliable
尽管此方法已废弃,但不会从 Tokio 中移除。
请注意,将 SO_LINGER 设为 0 这一特殊情况不会导致阻塞。Tokio 为此提供了 set_zero_linger。
§示例
use tokio::net::TcpStream;
let stream = TcpStream::connect("127.0.0.1:8080").await?;
stream.set_linger(None)?;Sourcepub fn set_zero_linger(&self) -> Result<()>
pub fn set_zero_linger(&self) -> Result<()>
通过设置 SO_LINGER 选项,将该套接字的 linger 时间设置为零。
这会在套接字被丢弃或关闭时强制中止连接(“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));Sourcepub 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)?;Sourcepub fn split<'a>(&'a mut self) -> (ReadHalf<'a>, WriteHalf<'a>)
pub fn split<'a>(&'a mut self) -> (ReadHalf<'a>, WriteHalf<'a>)
将一个 TcpStream 拆分为读半部和写半部,可用于并发地对该流进行读写操作。
此方法比 into_split 更高效,但拆分出的两半不能被移动到相互独立的任务中。
Sourcepub fn into_split(self) -> (OwnedReadHalf, OwnedWriteHalf)
pub fn into_split(self) -> (OwnedReadHalf, OwnedWriteHalf)
将一个 TcpStream 拆分为读半部和写半部,可用于并发地对该流进行读写操作。
与 split 不同,拥有的两半可以被移动到不同的任务中,但代价是一次堆内存分配。
注意:丢弃写半部会关闭 TCP 流的写半部。这等同于对 TcpStream 调用 shutdown()。
Trait 实现§
Source§impl AsRawSocket for TcpStream
Available on docsrs, or Windows only.
impl AsRawSocket for TcpStream
docsrs, or Windows only.Source§fn as_raw_socket(&self) -> RawSocket
fn as_raw_socket(&self) -> RawSocket
Source§impl AsRef<TcpStream> for OwnedReadHalf
impl AsRef<TcpStream> for OwnedReadHalf
Source§impl AsRef<TcpStream> for OwnedWriteHalf
impl AsRef<TcpStream> for OwnedWriteHalf
Source§impl AsSocket for TcpStream
Available on docsrs, or Windows only.
impl AsSocket for TcpStream
docsrs, or Windows only.Source§fn as_socket(&self) -> BorrowedSocket<'_>
fn as_socket(&self) -> BorrowedSocket<'_>
Source§impl AsyncWrite for TcpStream
impl AsyncWrite for TcpStream
Source§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. 更多信息Source§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. 更多信息Source§fn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
poll_write_vectored
implementation. 更多信息自动 Trait 实现§
impl !Freeze for TcpStream
impl RefUnwindSafe for TcpStream
impl Send for TcpStream
impl Sync for TcpStream
impl Unpin for TcpStream
impl UnsafeUnpin for TcpStream
impl UnwindSafe for TcpStream
Blanket 实现§
Source§impl<R> AsyncReadExt for R
impl<R> AsyncReadExt for R
Source§fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>where
Self: Unpin,
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>where
Self: Unpin,
Source§fn read_buf<'a, B>(&'a mut self, buf: &'a mut B) -> ReadBuf<'a, Self, B>
fn read_buf<'a, B>(&'a mut self, buf: &'a mut B) -> ReadBuf<'a, Self, B>
Source§fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self>where
Self: Unpin,
fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self>where
Self: Unpin,
buf. 更多信息Source§fn read_u8(&mut self) -> ReadU8<&mut Self>where
Self: Unpin,
fn read_u8(&mut self) -> ReadU8<&mut Self>where
Self: Unpin,
Source§fn read_i8(&mut self) -> ReadI8<&mut Self>where
Self: Unpin,
fn read_i8(&mut self) -> ReadI8<&mut Self>where
Self: Unpin,
Source§fn read_u16(&mut self) -> ReadU16<&mut Self>where
Self: Unpin,
fn read_u16(&mut self) -> ReadU16<&mut Self>where
Self: Unpin,
Source§fn read_i16(&mut self) -> ReadI16<&mut Self>where
Self: Unpin,
fn read_i16(&mut self) -> ReadI16<&mut Self>where
Self: Unpin,
Source§fn read_u32(&mut self) -> ReadU32<&mut Self>where
Self: Unpin,
fn read_u32(&mut self) -> ReadU32<&mut Self>where
Self: Unpin,
Source§fn read_i32(&mut self) -> ReadI32<&mut Self>where
Self: Unpin,
fn read_i32(&mut self) -> ReadI32<&mut Self>where
Self: Unpin,
Source§fn read_u64(&mut self) -> ReadU64<&mut Self>where
Self: Unpin,
fn read_u64(&mut self) -> ReadU64<&mut Self>where
Self: Unpin,
Source§fn read_i64(&mut self) -> ReadI64<&mut Self>where
Self: Unpin,
fn read_i64(&mut self) -> ReadI64<&mut Self>where
Self: Unpin,
Source§fn read_u128(&mut self) -> ReadU128<&mut Self>where
Self: Unpin,
fn read_u128(&mut self) -> ReadU128<&mut Self>where
Self: Unpin,
Source§fn read_i128(&mut self) -> ReadI128<&mut Self>where
Self: Unpin,
fn read_i128(&mut self) -> ReadI128<&mut Self>where
Self: Unpin,
Source§fn read_f32(&mut self) -> ReadF32<&mut Self>where
Self: Unpin,
fn read_f32(&mut self) -> ReadF32<&mut Self>where
Self: Unpin,
Source§fn read_f64(&mut self) -> ReadF64<&mut Self>where
Self: Unpin,
fn read_f64(&mut self) -> ReadF64<&mut Self>where
Self: Unpin,
Source§fn read_u16_le(&mut self) -> ReadU16Le<&mut Self>where
Self: Unpin,
fn read_u16_le(&mut self) -> ReadU16Le<&mut Self>where
Self: Unpin,
Source§fn read_i16_le(&mut self) -> ReadI16Le<&mut Self>where
Self: Unpin,
fn read_i16_le(&mut self) -> ReadI16Le<&mut Self>where
Self: Unpin,
Source§fn read_u32_le(&mut self) -> ReadU32Le<&mut Self>where
Self: Unpin,
fn read_u32_le(&mut self) -> ReadU32Le<&mut Self>where
Self: Unpin,
Source§fn read_i32_le(&mut self) -> ReadI32Le<&mut Self>where
Self: Unpin,
fn read_i32_le(&mut self) -> ReadI32Le<&mut Self>where
Self: Unpin,
Source§fn read_u64_le(&mut self) -> ReadU64Le<&mut Self>where
Self: Unpin,
fn read_u64_le(&mut self) -> ReadU64Le<&mut Self>where
Self: Unpin,
Source§fn read_i64_le(&mut self) -> ReadI64Le<&mut Self>where
Self: Unpin,
fn read_i64_le(&mut self) -> ReadI64Le<&mut Self>where
Self: Unpin,
Source§fn read_u128_le(&mut self) -> ReadU128Le<&mut Self>where
Self: Unpin,
fn read_u128_le(&mut self) -> ReadU128Le<&mut Self>where
Self: Unpin,
Source§fn read_i128_le(&mut self) -> ReadI128Le<&mut Self>where
Self: Unpin,
fn read_i128_le(&mut self) -> ReadI128Le<&mut Self>where
Self: Unpin,
Source§fn read_f32_le(&mut self) -> ReadF32Le<&mut Self>where
Self: Unpin,
fn read_f32_le(&mut self) -> ReadF32Le<&mut Self>where
Self: Unpin,
Source§fn read_f64_le(&mut self) -> ReadF64Le<&mut Self>where
Self: Unpin,
fn read_f64_le(&mut self) -> ReadF64Le<&mut Self>where
Self: Unpin,
Source§fn read_to_end<'a>(&'a mut self, buf: &'a mut Vec<u8>) -> ReadToEnd<'a, Self>where
Self: Unpin,
fn read_to_end<'a>(&'a mut self, buf: &'a mut Vec<u8>) -> ReadToEnd<'a, Self>where
Self: Unpin,
buf. 更多信息