How to check for internet connection?

I need a minimal way to check for internet connection.

use std::net::UdpSocket;

fn main() {
    active_internet_connection();
}

fn active_internet_connection() {
    UdpSocket::bind("1.1.1.1:53").unwrap();
}

I need a function that returns true if internet connection is on and returns false if internet connection is off.

This code doesn't work because it always panicks which means that it can't connect.
Is there any other way to do it?

Depends on what level of internet connectivity you need? Is just being connected to a router enough? Do you need to connect to a wider part of the internet? Or do you need uncensored access to the entire internet? Browsers and phones generally check for captive portals by connecting to a website of the vendor over http (not https) and checking that the result matches expectation rather than redirecting to the captive portal itself.

1 Like

I'm used to testing network connections by using the 'ping' command to contact whatever it is you hope to be connected to:

# ping google.com

I have never tried any of them but there are a lot of crates that can ping from Rust:
https://crates.io/keywords/ping

That is a little high level. It assumes the IP address of google.com can be found from a Domain Name Server (DNS). Google has a DNS service:

# ping 8.8.8.8

There are crates that will use DNS to look up addresses from domain names:https://crates.io/search?q=domain%20lookup%20

Yes I could use "ping" to check for an internet connection. I don't want to use a crate as I want to keep my project minimal.

As you can see in my code I have tried creating a udp connection but it can't connect to the server and it always fails.

I want to see if the computer can connect to the internet and access for example google.com.

I became curious how they check for internet connectivity recently because my Windows machine often tells me that my WiFi is connected to my phone(or mobile modem/router) but "No Internet Connection". But everything works fine though my browser or whatever other connectivity I use.

Looks like as a minimum you need the ICMP protocol to make a "ping". There is a crate for that:icmp::IcmpSocket - Rust. If you don't want to use a crate you will have to write your own to do ICMP. Or copy the code from IcmpSocket crate.

The UDP protocol does not have any notion of connections. With UDP you use send packets of data out to some address and it sends them. There is no checking that the packet arrives at the other end. No responses at all.

The code you have shown there does not try to make a connection with anything. It does not send anything to anything. It only binds you to an IP address and port number. Which basically means that any packets you do eventually send will contain that IP address and port number as their source IP and port.

You could use use std::net::TcpStream TcpStream in std::net - Rust

use std::io::prelude::*;
use std::net::TcpStream;

fn main() -> std::io::Result<()> {
    let mut stream = TcpStream::connect("64.233.161.100")?;

    stream.write(&[1])?;
    stream.read(&mut [0; 128])?;
    Ok(())
} // the stream is closed here

Can't you just try to create a UDP or TCP to a server online and if it fails you can see that there is no internet connection. That is what I am trying to do as the features are already in the Rust std.

I get

Error: Error { kind: InvalidInput, message: "invalid socket address" }

This is also what I got when I tried to create a UDP connection.

So you have an incorrect socket address.

This works:

let mut stream = TcpStream::connect("209.85.233.101:80")?;

Which is the address I get for google.com when I do a ping. And port 80 which is the standard port number for insecure HTTP.

It worked thank you! Is there any way to do this in UDP?

Not really possible with UDP.

As I said above, with UDP you send individual packets to remote IP addresses. There is no "connection" There is no response. There is way to know the packet arrived at the other end. Or even that it did not get lost along the route through intermediate routers on the internet.

Unless....unless you have something running on the remote address that also uses UDP and will make replies to whatever UDP packets you send it. I guess you do not.

1 Like

Due to firewalls, NATs and other middleboxes there are different degrees of "internet access". Does hostname resolution work? HTTP? any TCP port? are listening ports externally reachable? UDP? Any IP protocol? IPv4 or IPv6?
And even if those work, do they work reliably and fast enough? E.g. a small-packet ping may succeed but big packets can get lost due to MTU problems. Or some ISPs kill TCP connections when they look like traffic they don't like (e.g. VPNs or p2p applications). And just because one remote host is reachable doesn't mean others are, sometimes there are routing issues. E.g. my ISP had IPv6 peering issues with cloudflare a while back, which made services behind cloudflare only IPv4-reachable, but other IPv6 services worked fine.

Depending on what your software needs you'll have to test different things.

Well, at least on linux you can listen for the ICMP errors in reply to a UDP packet (via MSG_ERRQUEUE, this doesn't need extra privileges). That's how UDP traceroutes work.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.