I'd like to send an HTTPS request over UDP to a server on the internet (where I don't know if the server supports HTTPS over UDP). As a toy example, right now, I'm trying to send a GET request to http://httpbin.org/get. How do I do this?
Right now, I'm doing this in Rust, and my code looks like this:
fn main() {
use std::net::ToSocketAddrs;
let socket = std::net::UdpSocket::bind("127.0.0.1:34254").unwrap();
let remote_addr: std::net::SocketAddr = "httpbin.org:80".to_socket_addrs().unwrap().next().unwrap();
socket.connect(remote_addr).unwrap();
let msg = "GET /get HTTP/1.1\r\nHost: httpbin.org\r\naccept: application/json\r\n\r\n\r\n";
socket.send(msg.as_bytes()).unwrap();
let mut buf = [0; 5000];
let num_bytes = socket.recv(&mut buf).unwrap();
println!("recieved {} bytes: {:?}", num_bytes, std::str::from_utf8(&buf[..num_bytes]));
}
However, when I run the code I get the following output:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" }', ...
(this happens on the socket.connect(...)
line)
Is what I'm doing even possible? Or am I doing it wrong? Any help would be greatly appreciated!
CodePudding user response:
As Finomnis pointed out, there are several questions here so I will choose to answer only one of them - namely how to fix the error you are experiencing.
Your issue comes from binding the UDP socket on 127.0.0.1
. Since this is a local address, the socket will only bind to the local interface and you will be able to communicate with local hosts only.
As you want to connect to a remote server, you should instead bind to 0.0.0.0
, which is a shorthand for all network interfaces:
let socket = std::net::UdpSocket::bind("0.0.0.0:34254").unwrap();
With this change the code no longer panics, but instead hangs on socket.recv()
.
Since it's unlikely that httpbin.org
is ready to respond to this request, you will probably never get a response.
PS: When saying HTTPS over UDP, you might be thinking of HTTP/3 which is indeed based on UDP, but is a much more complicated protocol that HTTP/1.
CodePudding user response:
You can't send a message to an external IP address from a socket that is bound to 127.0.0.1
.
Tell the operating system that it should figure out where to bind it instead:
let socket = std::net::UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 0)).unwrap();
Apart of that, you most likely won't get an answer, because http
/https
usually does not use UDP
, it uses TCP
. The webservers will not listen on UDP
port 80
.