mirror of
https://github.com/tokio-rs/tokio.git
synced 2025-09-25 12:00:35 +00:00
net: add TcpStream::quickack
and TcpStream::set_quickack
(#7490)
Signed-off-by: ADD-SP <qiqi.zhang@konghq.com>
This commit is contained in:
parent
01ea8f22ea
commit
5f04d14d81
@ -1170,6 +1170,71 @@ impl TcpStream {
|
||||
self.io.set_nodelay(nodelay)
|
||||
}
|
||||
|
||||
/// Gets the value of the `TCP_QUICKACK` option on this socket.
|
||||
///
|
||||
/// For more information about this option, see [`TcpStream::set_quickack`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::net::TcpStream;
|
||||
///
|
||||
/// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let stream = TcpStream::connect("127.0.0.1:8080").await?;
|
||||
///
|
||||
/// stream.quickack()?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(any(target_os = "linux", target_os = "android", target_os = "fuchsia")))
|
||||
)]
|
||||
pub fn quickack(&self) -> io::Result<bool> {
|
||||
socket2::SockRef::from(self).tcp_quickack()
|
||||
}
|
||||
|
||||
/// Enable or disable `TCP_QUICKACK`.
|
||||
///
|
||||
/// This flag causes Linux to eagerly send `ACK`s rather than delaying them.
|
||||
/// Linux may reset this flag after further operations on the socket.
|
||||
///
|
||||
/// See [`man 7 tcp`](https://man7.org/linux/man-pages/man7/tcp.7.html) and
|
||||
/// [TCP delayed acknowledgment](https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment)
|
||||
/// for more information.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::net::TcpStream;
|
||||
///
|
||||
/// # async fn dox() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let stream = TcpStream::connect("127.0.0.1:8080").await?;
|
||||
///
|
||||
/// stream.set_quickack(true)?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(any(target_os = "linux", target_os = "android", target_os = "fuchsia")))
|
||||
)]
|
||||
pub fn set_quickack(&self, quickack: bool) -> io::Result<()> {
|
||||
socket2::SockRef::from(self).set_tcp_quickack(quickack)
|
||||
}
|
||||
|
||||
cfg_not_wasi! {
|
||||
/// Reads the linger duration for this socket by getting the `SO_LINGER`
|
||||
/// option.
|
||||
|
71
tokio/tests/net_quickack.rs
Normal file
71
tokio/tests/net_quickack.rs
Normal file
@ -0,0 +1,71 @@
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![cfg(all(
|
||||
feature = "net",
|
||||
any(
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_os = "cygwin",
|
||||
)
|
||||
))]
|
||||
#![cfg(not(miri))] // No `socket` in miri.
|
||||
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::sync::oneshot;
|
||||
|
||||
#[tokio::test]
|
||||
async fn socket_works_with_quickack() {
|
||||
const MESSAGE: &str = "Hello, tokio!";
|
||||
|
||||
let (tx_port, rx_port) = oneshot::channel();
|
||||
|
||||
let server = tokio::spawn(async move {
|
||||
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
|
||||
let addr = listener.local_addr().unwrap();
|
||||
|
||||
tx_port.send(addr.port()).unwrap();
|
||||
|
||||
let (mut stream, _) = listener.accept().await.unwrap();
|
||||
stream.set_quickack(true).unwrap();
|
||||
assert!(stream.quickack().unwrap());
|
||||
|
||||
stream.write_all(MESSAGE.as_bytes()).await.unwrap();
|
||||
|
||||
let mut buf = vec![0; MESSAGE.len()];
|
||||
stream.read_exact(&mut buf).await.unwrap();
|
||||
assert_eq!(buf, MESSAGE.as_bytes());
|
||||
|
||||
// There is nothing special about setting quickack to false
|
||||
// at this point, we just want to test the `false` case.
|
||||
stream.set_quickack(false).unwrap();
|
||||
assert!(!stream.quickack().unwrap());
|
||||
|
||||
stream.shutdown().await.unwrap();
|
||||
});
|
||||
|
||||
let port = rx_port.await.unwrap();
|
||||
let client = tokio::spawn(async move {
|
||||
let mut stream = TcpStream::connect(format!("127.0.0.1:{port}"))
|
||||
.await
|
||||
.unwrap();
|
||||
stream.set_quickack(true).unwrap();
|
||||
assert!(stream.quickack().unwrap());
|
||||
|
||||
let mut buf = vec![0; MESSAGE.len()];
|
||||
stream.read_exact(&mut buf).await.unwrap();
|
||||
assert_eq!(buf, MESSAGE.as_bytes());
|
||||
|
||||
stream.write_all(MESSAGE.as_bytes()).await.unwrap();
|
||||
|
||||
// There is nothing special about setting quickack to false
|
||||
// at this point, we just want to test the `false` case.
|
||||
stream.set_quickack(false).unwrap();
|
||||
assert!(!stream.quickack().unwrap());
|
||||
|
||||
stream.shutdown().await.unwrap();
|
||||
});
|
||||
|
||||
tokio::try_join!(server, client).unwrap();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user