cfg_net! { /// A TCP socket that has not yet been converted to a `TcpStream` or /// `TcpListener`. /// /// `TcpSocket` wraps an operating system socket and enables the caller to /// configure the socket before establishing a TCP connection or accepting /// inbound connections. The caller is able to set socket option and explicitly /// bind the socket with a socket address. /// /// The underlying socket is closed when the `TcpSocket` value is dropped. /// /// `TcpSocket` should only be used directly if the default configuration used /// by `TcpStream::connect` and `TcpListener::bind` does not meet the required /// use case. /// /// Calling `TcpStream::connect("127.0.0.1:8080")` is equivalent to: /// /// ```no_run /// 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?; /// # drop(stream); /// /// Ok(()) /// } /// ``` /// /// Calling `TcpListener::bind("127.0.0.1:8080")` is equivalent to: /// /// ```no_run /// 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()?; /// // 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)?; /// /// // Note: the actual backlog used by `TcpListener::bind` is platform-dependent, /// // as Tokio relies on Mio's default backlog value configuration. The `1024` here is only /// // illustrative and does not reflect the real value used. /// let listener = socket.listen(1024)?; /// # drop(listener); /// /// Ok(()) /// } /// ``` /// /// Setting socket options not explicitly provided by `TcpSocket` may be done by /// accessing the `RawFd`/`RawSocket` using [`AsRawFd`]/[`AsRawSocket`] and /// setting the option with a crate like [`socket2`]. /// /// [`RawFd`]: https://doc.rust-lang.org/std/os/fd/type.RawFd.html /// [`RawSocket`]: https://doc.rust-lang.org/std/os/windows/io/type.RawSocket.html /// [`AsRawFd`]: https://doc.rust-lang.org/std/os/fd/trait.AsRawFd.html /// [`AsRawSocket`]: https://doc.rust-lang.org/std/os/windows/io/trait.AsRawSocket.html /// [`socket2`]: https://docs.rs/socket2/ #[cfg_attr(docsrs, doc(alias = "connect_std"))] pubstruct TcpSocket {
inner: socket2::Socket,
}
}
impl TcpSocket { /// Creates a new socket configured for IPv4. /// /// Calls `socket(2)` with `AF_INET` and `SOCK_STREAM`. /// /// # Returns /// /// On success, the newly created `TcpSocket` is returned. If an error is /// encountered, it is returned instead. /// /// # Examples /// /// Create a new IPv4 socket and start listening. /// /// ```no_run /// 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()?; /// socket.bind(addr)?; /// /// let listener = socket.listen(128)?; /// # drop(listener); /// Ok(()) /// } /// ``` pubfn new_v4() -> io::Result<TcpSocket> {
TcpSocket::new(socket2::Domain::IPV4)
}
/// Creates a new socket configured for IPv6. /// /// Calls `socket(2)` with `AF_INET6` and `SOCK_STREAM`. /// /// # Returns /// /// On success, the newly created `TcpSocket` is returned. If an error is /// encountered, it is returned instead. /// /// # Examples /// /// Create a new IPv6 socket and start listening. /// /// ```no_run /// use tokio::net::TcpSocket; /// /// use std::io; /// /// #[tokio::main] /// async fn main() -> io::Result<()> { /// let addr = "[::1]:8080".parse().unwrap(); /// let socket = TcpSocket::new_v6()?; /// socket.bind(addr)?; /// /// let listener = socket.listen(128)?; /// # drop(listener); /// Ok(()) /// } /// ``` pubfn new_v6() -> io::Result<TcpSocket> {
TcpSocket::new(socket2::Domain::IPV6)
}
/// Sets value for the `SO_KEEPALIVE` option on this socket. pubfn set_keepalive(&self, keepalive: bool) -> io::Result<()> { self.inner.set_keepalive(keepalive)
}
/// Gets the value of the `SO_KEEPALIVE` option on this socket. pubfn keepalive(&self) -> io::Result<bool> { self.inner.keepalive()
}
/// Allows the socket to bind to an in-use address. /// /// Behavior is platform specific. Refer to the target platform's /// documentation for more details. /// /// # Examples /// /// ```no_run /// 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()?; /// socket.set_reuseaddr(true)?; /// socket.bind(addr)?; /// /// let listener = socket.listen(1024)?; /// # drop(listener); /// /// Ok(()) /// } /// ``` pubfn set_reuseaddr(&self, reuseaddr: bool) -> io::Result<()> { self.inner.set_reuse_address(reuseaddr)
}
/// Retrieves the value set for `SO_REUSEADDR` on this socket. /// /// # Examples /// /// ```no_run /// 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()?; /// socket.set_reuseaddr(true)?; /// assert!(socket.reuseaddr().unwrap()); /// socket.bind(addr)?; /// /// let listener = socket.listen(1024)?; /// Ok(()) /// } /// ``` pubfn reuseaddr(&self) -> io::Result<bool> { self.inner.reuse_address()
}
/// Allows the socket to bind to an in-use port. Only available for unix systems /// (excluding Solaris, Illumos, and Cygwin). /// /// Behavior is platform specific. Refer to the target platform's /// documentation for more details. /// /// # Examples /// /// ```no_run /// 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()?; /// socket.set_reuseport(true)?; /// socket.bind(addr)?; /// /// let listener = socket.listen(1024)?; /// Ok(()) /// } /// ``` #[cfg(all(
unix,
not(target_os = "solaris"),
not(target_os = "illumos"),
not(target_os = "cygwin"),
))] #[cfg_attr(
docsrs,
doc(cfg(all(
unix,
not(target_os = "solaris"),
not(target_os = "illumos"),
not(target_os = "cygwin"),
)))
)] pubfn set_reuseport(&self, reuseport: bool) -> io::Result<()> { self.inner.set_reuse_port(reuseport)
}
/// Allows the socket to bind to an in-use port. Only available for unix systems /// (excluding Solaris, Illumos, and Cygwin). /// /// Behavior is platform specific. Refer to the target platform's /// documentation for more details. /// /// # Examples /// /// ```no_run /// 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()?; /// socket.set_reuseport(true)?; /// assert!(socket.reuseport().unwrap()); /// socket.bind(addr)?; /// /// let listener = socket.listen(1024)?; /// Ok(()) /// } /// ``` #[cfg(all(
unix,
not(target_os = "solaris"),
not(target_os = "illumos"),
not(target_os = "cygwin"),
))] #[cfg_attr(
docsrs,
doc(cfg(all(
unix,
not(target_os = "solaris"),
not(target_os = "illumos"),
not(target_os = "cygwin"),
)))
)] pubfn reuseport(&self) -> io::Result<bool> { self.inner.reuse_port()
}
/// Sets the size of the TCP send buffer on this socket. /// /// On most operating systems, this sets the `SO_SNDBUF` socket option. pubfn set_send_buffer_size(&self, size: u32) -> io::Result<()> { self.inner.set_send_buffer_size(size as usize)
}
/// Returns the size of the TCP send buffer for this socket. /// /// On most operating systems, this is the value of the `SO_SNDBUF` socket /// option. /// /// Note that if [`set_send_buffer_size`] has been called on this socket /// previously, the value returned by this function may not be the same as /// the argument provided to `set_send_buffer_size`. This is for the /// following reasons: /// /// * Most operating systems have minimum and maximum allowed sizes for the /// send buffer, and will clamp the provided value if it is below the /// minimum or above the maximum. The minimum and maximum buffer sizes are /// OS-dependent. /// * Linux will double the buffer size to account for internal bookkeeping /// data, and returns the doubled value from `getsockopt(2)`. As per `man /// 7 socket`: /// > Sets or gets the maximum socket send buffer in bytes. The /// > kernel doubles this value (to allow space for bookkeeping /// > overhead) when it is set using `setsockopt(2)`, and this doubled /// > value is returned by `getsockopt(2)`. /// /// [`set_send_buffer_size`]: #method.set_send_buffer_size pubfn send_buffer_size(&self) -> io::Result<u32> { self.inner.send_buffer_size().map(|n| n as u32)
}
/// Sets the size of the TCP receive buffer on this socket. /// /// On most operating systems, this sets the `SO_RCVBUF` socket option. pubfn set_recv_buffer_size(&self, size: u32) -> io::Result<()> { self.inner.set_recv_buffer_size(size as usize)
}
/// Returns the size of the TCP receive buffer for this socket. /// /// On most operating systems, this is the value of the `SO_RCVBUF` socket /// option. /// /// Note that if [`set_recv_buffer_size`] has been called on this socket /// previously, the value returned by this function may not be the same as /// the argument provided to `set_recv_buffer_size`. This is for the /// following reasons: /// /// * Most operating systems have minimum and maximum allowed sizes for the /// receive buffer, and will clamp the provided value if it is below the /// minimum or above the maximum. The minimum and maximum buffer sizes are /// OS-dependent. /// * Linux will double the buffer size to account for internal bookkeeping /// data, and returns the doubled value from `getsockopt(2)`. As per `man /// 7 socket`: /// > Sets or gets the maximum socket send buffer in bytes. The /// > kernel doubles this value (to allow space for bookkeeping /// > overhead) when it is set using `setsockopt(2)`, and this doubled /// > value is returned by `getsockopt(2)`. /// /// [`set_recv_buffer_size`]: #method.set_recv_buffer_size pubfn recv_buffer_size(&self) -> io::Result<u32> { self.inner.recv_buffer_size().map(|n| n as u32)
}
/// Sets the linger duration of this socket by setting the `SO_LINGER` option. /// /// This option controls the action taken when a stream has unsent messages and the stream is /// closed. If `SO_LINGER` is set, the system shall block the process until it can transmit the /// data or until the time expires. /// /// If `SO_LINGER` is not specified, and the socket is closed, the system handles the call in a /// way that allows the process to continue as quickly as possible. /// /// This option is deprecated because setting `SO_LINGER` on a socket used with Tokio is always /// incorrect as it leads to blocking the thread when the socket is closed. For more details, /// please see: /// /// > Volumes of communications have been devoted to the intricacies of `SO_LINGER` versus /// > non-blocking (`O_NONBLOCK`) sockets. From what I can tell, the final word is: don't do /// > it. Rely on the `shutdown()`-followed-by-`read()`-eof technique instead. /// > /// > From [The ultimate `SO_LINGER` page, or: why is my tcp not reliable](https://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable) /// /// Although this method is deprecated, it will not be removed from Tokio. /// /// Note that the special case of setting `SO_LINGER` to zero does not lead to blocking. Tokio /// provides [`set_zero_linger`](Self::set_zero_linger) for this purpose. #[deprecated = "`SO_LINGER` causes the socket to block the thread on drop"] pubfn set_linger(&self, dur: Option<Duration>) -> io::Result<()> { self.inner.set_linger(dur)
}
/// Sets a linger duration of zero on this socket by setting the `SO_LINGER` option. /// /// This causes the connection to be forcefully aborted ("abortive close") when the socket is /// dropped or closed. Instead of the normal TCP shutdown handshake (`FIN`/`ACK`), a TCP `RST` /// (reset) segment is sent to the peer, and the socket immediately discards any unsent data /// residing in the socket send buffer. This prevents the socket from entering the `TIME_WAIT` /// state after closing it. /// /// This is a destructive action. Any data currently buffered by the OS but not yet transmitted /// will be lost. The peer will likely receive a "Connection Reset" error rather than a clean /// end-of-stream. /// /// See the documentation for [`set_linger`](Self::set_linger) for additional details on how /// `SO_LINGER` works. pubfn set_zero_linger(&self) -> io::Result<()> { self.inner.set_linger(Some(Duration::ZERO))
}
/// Reads the linger duration for this socket by getting the `SO_LINGER` /// option. /// /// For more information about this option, see [`set_zero_linger`] and [`set_linger`]. /// /// [`set_linger`]: TcpSocket::set_linger /// [`set_zero_linger`]: TcpSocket::set_zero_linger pubfn linger(&self) -> io::Result<Option<Duration>> { self.inner.linger()
}
/// Sets the value of the `TCP_NODELAY` option on this socket. /// /// If set, this option disables the Nagle algorithm. This means that segments are always /// sent as soon as possible, even if there is only a small amount of data. When not set, /// data is buffered until there is a sufficient amount to send out, thereby avoiding /// the frequent sending of small packets. /// /// # Examples /// /// ```no_run /// use tokio::net::TcpSocket; /// /// # async fn dox() -> Result<(), Box<dyn std::error::Error>> { /// let socket = TcpSocket::new_v4()?; /// /// socket.set_nodelay(true)?; /// # Ok(()) /// # } /// ``` pubfn set_nodelay(&self, nodelay: bool) -> io::Result<()> { self.inner.set_tcp_nodelay(nodelay)
}
/// Gets the value of the `TCP_NODELAY` option on this socket. /// /// For more information about this option, see [`set_nodelay`]. /// /// [`set_nodelay`]: TcpSocket::set_nodelay /// /// # Examples /// /// ```no_run /// use tokio::net::TcpSocket; /// /// # async fn dox() -> Result<(), Box<dyn std::error::Error>> { /// let socket = TcpSocket::new_v4()?; /// /// println!("{:?}", socket.nodelay()?); /// # Ok(()) /// # } /// ``` pubfn nodelay(&self) -> io::Result<bool> { self.inner.tcp_nodelay()
}
/// Gets the value of the `IPV6_TCLASS` option for this socket. /// /// For more information about this option, see [`set_tclass_v6`]. /// /// [`set_tclass_v6`]: Self::set_tclass_v6 // https://docs.rs/socket2/0.6.1/src/socket2/sys/unix.rs.html#2541 #[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
))] #[cfg_attr(
docsrs,
doc(cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
)))
)] pubfn tclass_v6(&self) -> io::Result<u32> { self.inner.tclass_v6()
}
/// Sets the value for the `IPV6_TCLASS` option on this socket. /// /// Specifies the traffic class field that is used in every packet /// sent from this socket. /// /// # Note /// /// This may not have any effect on IPv4 sockets. // https://docs.rs/socket2/0.6.1/src/socket2/sys/unix.rs.html#2566 #[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
))] #[cfg_attr(
docsrs,
doc(cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
)))
)] pubfn set_tclass_v6(&self, tclass: u32) -> io::Result<()> { self.inner.set_tclass_v6(tclass)
}
/// Gets the value of the `IP_TOS` option for this socket. /// /// For more information about this option, see [`set_tos_v4`]. /// /// [`set_tos_v4`]: Self::set_tos_v4 // https://docs.rs/socket2/0.6.1/src/socket2/socket.rs.html#1585 #[cfg(not(any(
target_os = "fuchsia",
target_os = "redox",
target_os = "solaris",
target_os = "illumos",
target_os = "haiku",
target_os = "wasi",
)))] #[cfg_attr(
docsrs,
doc(cfg(not(any(
target_os = "fuchsia",
target_os = "redox",
target_os = "solaris",
target_os = "illumos",
target_os = "haiku",
target_os = "wasi",
))))
)] pubfn tos_v4(&self) -> io::Result<u32> { self.inner.tos_v4()
}
/// Sets the value for the `IP_TOS` option on this socket. /// /// This value sets the type-of-service field that is used in every packet /// sent from this socket. /// /// # Note /// /// - This may not have any effect on IPv6 sockets. /// - On Windows, `IP_TOS` is only supported on [Windows 8+ or /// Windows Server 2012+.](https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options) // https://docs.rs/socket2/0.6.1/src/socket2/socket.rs.html#1566 #[cfg(not(any(
target_os = "fuchsia",
target_os = "redox",
target_os = "solaris",
target_os = "illumos",
target_os = "haiku",
target_os = "wasi",
)))] #[cfg_attr(
docsrs,
doc(cfg(not(any(
target_os = "fuchsia",
target_os = "redox",
target_os = "solaris",
target_os = "illumos",
target_os = "haiku",
target_os = "wasi",
))))
)] pubfn set_tos_v4(&self, tos: u32) -> io::Result<()> { self.inner.set_tos_v4(tos)
}
/// Gets the value for the `SO_BINDTODEVICE` option on this socket /// /// This value gets the socket binded device's interface name. #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",))] #[cfg_attr(
docsrs,
doc(cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",)))
)] pubfn device(&self) -> io::Result<Option<Vec<u8>>> { self.inner.device()
}
/// Sets the value for the `SO_BINDTODEVICE` option on this socket /// /// If a socket is bound to an interface, only packets received from that /// particular interface are processed by the socket. Note that this only /// works for some socket types, particularly `AF_INET` sockets. /// /// If `interface` is `None` or an empty string it removes the binding. #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] #[cfg_attr(
docsrs,
doc(cfg(all(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))))
)] pubfn bind_device(&self, interface: Option<&[u8]>) -> io::Result<()> { self.inner.bind_device(interface)
}
/// Gets the local address of this socket. /// /// Will fail on windows if called before `bind`. /// /// # Examples /// /// ```no_run /// 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()?; /// socket.bind(addr)?; /// assert_eq!(socket.local_addr().unwrap().to_string(), "127.0.0.1:8080"); /// let listener = socket.listen(1024)?; /// Ok(()) /// } /// ``` pubfn local_addr(&self) -> io::Result<SocketAddr> { self.inner.local_addr().and_then(convert_address)
}
/// Returns the value of the `SO_ERROR` option. pubfn take_error(&self) -> io::Result<Option<io::Error>> { self.inner.take_error()
}
/// Binds the socket to the given address. /// /// This calls the `bind(2)` operating-system function. Behavior is /// platform specific. Refer to the target platform's documentation for more /// details. /// /// # Examples /// /// Bind a socket before listening. /// /// ```no_run /// 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()?; /// socket.bind(addr)?; /// /// let listener = socket.listen(1024)?; /// # drop(listener); /// /// Ok(()) /// } /// ``` pubfn bind(&self, addr: SocketAddr) -> io::Result<()> { self.inner.bind(&addr.into())
}
/// Establishes a TCP connection with a peer at the specified socket address. /// /// The `TcpSocket` is consumed. Once the connection is established, a /// connected [`TcpStream`] is returned. If the connection fails, the /// encountered error is returned. /// /// [`TcpStream`]: TcpStream /// /// This calls the `connect(2)` operating-system function. Behavior is /// platform specific. Refer to the target platform's documentation for more /// details. /// /// # Examples /// /// Connecting to a peer. /// /// ```no_run /// 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?; /// # drop(stream); /// /// Ok(()) /// } /// ``` pubasyncfn connect(self, addr: SocketAddr) -> io::Result<TcpStream> { iflet Err(err) = self.inner.connect(&addr.into()) { #[cfg(not(windows))] if err.raw_os_error() != Some(libc::EINPROGRESS) { return Err(err);
} #[cfg(windows)] if err.kind() != io::ErrorKind::WouldBlock { return Err(err);
}
} #[cfg(not(windows))] let mio = { use std::os::fd::{FromRawFd, IntoRawFd};
let raw_fd = self.inner.into_raw_fd(); unsafe { mio::net::TcpStream::from_raw_fd(raw_fd) }
};
#[cfg(windows)] let mio = { use std::os::windows::io::{FromRawSocket, IntoRawSocket};
let raw_socket = self.inner.into_raw_socket(); unsafe { mio::net::TcpStream::from_raw_socket(raw_socket) }
};
TcpStream::connect_mio(mio).await
}
/// Converts the socket into a `TcpListener`. /// /// `backlog` defines the maximum number of pending connections are queued /// by the operating system at any given time. Connection are removed from /// the queue with [`TcpListener::accept`]. When the queue is full, the /// operating-system will start rejecting connections. /// /// [`TcpListener::accept`]: TcpListener::accept /// /// This calls the `listen(2)` operating-system function, marking the socket /// as a passive socket. Behavior is platform specific. Refer to the target /// platform's documentation for more details. /// /// # Examples /// /// Create a `TcpListener`. /// /// ```no_run /// 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()?; /// socket.bind(addr)?; /// /// let listener = socket.listen(1024)?; /// # drop(listener); /// /// Ok(()) /// } /// ``` pubfn listen(self, backlog: u32) -> io::Result<TcpListener> { self.inner.listen(backlog as i32)?; #[cfg(not(windows))] let mio = { use std::os::fd::{FromRawFd, IntoRawFd};
let raw_fd = self.inner.into_raw_fd(); unsafe { mio::net::TcpListener::from_raw_fd(raw_fd) }
};
#[cfg(windows)] let mio = { use std::os::windows::io::{FromRawSocket, IntoRawSocket};
let raw_socket = self.inner.into_raw_socket(); unsafe { mio::net::TcpListener::from_raw_socket(raw_socket) }
};
TcpListener::new(mio)
}
/// Converts a [`std::net::TcpStream`] into a `TcpSocket`. The provided /// socket must not have been connected prior to calling this function. This /// function is typically used together with crates such as [`socket2`] to /// configure socket options that are not available on `TcpSocket`. /// /// [`std::net::TcpStream`]: struct@std::net::TcpStream /// [`socket2`]: https://docs.rs/socket2/ /// /// # Notes /// /// The caller is responsible for ensuring that the socket is in /// non-blocking mode. Otherwise all I/O operations on the socket /// will block the thread, which will cause unexpected behavior. /// Non-blocking mode can be set using [`set_nonblocking`]. /// /// [`set_nonblocking`]: std::net::TcpStream::set_nonblocking /// /// # Examples /// /// ``` /// use tokio::net::TcpSocket; /// use socket2::{Domain, Socket, Type}; /// /// #[tokio::main] /// async fn main() -> std::io::Result<()> { /// # if cfg!(miri) { return Ok(()); } // No `socket` in miri. /// let socket2_socket = Socket::new(Domain::IPV4, Type::STREAM, None)?; /// socket2_socket.set_nonblocking(true)?; /// /// let socket = TcpSocket::from_std_stream(socket2_socket.into()); /// /// Ok(()) /// } /// ``` pubfn from_std_stream(std_stream: std::net::TcpStream) -> TcpSocket { #[cfg(not(windows))]
{ use std::os::fd::{FromRawFd, IntoRawFd};
let raw_fd = std_stream.into_raw_fd(); unsafe { TcpSocket::from_raw_fd(raw_fd) }
}
#[cfg(windows)]
{ use std::os::windows::io::{FromRawSocket, IntoRawSocket};
// These trait implementations can't be build on Windows, so we completely // ignore them, even when building documentation. #[cfg(any(unix, target_os = "wasi"))]
cfg_unix_or_wasi! { impl AsRawFd for TcpSocket { fn as_raw_fd(&self) -> RawFd { self.inner.as_raw_fd()
}
}
impl FromRawFd for TcpSocket { /// Converts a `RawFd` to a `TcpSocket`. /// /// # Notes /// /// The caller is responsible for ensuring that the socket is in /// non-blocking mode. unsafefn from_raw_fd(fd: RawFd) -> TcpSocket { // Safety: exactly the same safety requirements as the // `FromRawFd::from_raw_fd` trait method. let inner = unsafe { socket2::Socket::from_raw_fd(fd) };
TcpSocket { inner }
}
}
impl FromRawSocket for TcpSocket { /// Converts a `RawSocket` to a `TcpStream`. /// /// # Notes /// /// The caller is responsible for ensuring that the socket is in /// non-blocking mode. unsafefn from_raw_socket(socket: RawSocket) -> TcpSocket { let inner = unsafe { socket2::Socket::from_raw_socket(socket) };
TcpSocket { inner }
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.