How to bind() on TCP client side in rust/tokio?

那年仲夏 提交于 2020-08-08 06:03:23

问题


I have a need to make sure the client side of the TCP connection goes through a particular (IP) interface. The standard way would be to bind() the socket to the IP:0, before the connect().

I started looking at tokio::net::TcpStream::connect() and friends, which doesn't seem to have a way to do this. I took a step back and looked at std::net::TcpStream, which doesn't have it either.

Am I missing something, or do I need to go through some lower level APIs?


回答1:


The best way of doing this at the moment is indeed to use socket2 to create the socket and convert it into a Tokio TcpStream. In order to correctly handle the fact that the connection step will be blocking with this approach, you can use tokio::task::spawn_blocking.

use std::io::Result;

use tokio::task::spawn_blocking;
use tokio::net::TcpStream;

use socket2::{Socket, SockAddr, Domain, Type};

async fn connect_bind(bind: SockAddr, connect: SockAddr) -> Result<TcpStream> {
    spawn_blocking(move || {
        let socket = Socket::new(Domain::ipv4(), Type::stream(), None)?;
        socket.bind(&bind)?;
        socket.connect(&connect)?;
        TcpStream::from_std(socket.into_tcp_stream())
    }).await?
}

Using spawn_blocking like this is rather common — this is how Tokio implements file system operations.



来源:https://stackoverflow.com/questions/59298027/how-to-bind-on-tcp-client-side-in-rust-tokio

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!