HTTP communication between RPI and computer via an Ethernet cable

I want to have a Raspberry Pi and a PC that are connected with an Ethernet cable to communicate with each other via a server-client-HTTP.jl setup. I don’t know however what IP address I should use, or any additional steps I should take.

The RPI is the server with something like:

server = WebSockets.listen!("<some IP address>", 8081) do ws
    for msg in ws
        # do something with `msg` 
        # and `send` something back to `ws`
    end
end

and the computer is the client with something like:

WebSockets.open("ws://<some IP address>:8081") do ws
    send(ws, "a") # start the conversation
    for msg in ws
        # do something with `msg`
        # and `send` something back to `ws`
    end
end

The RPI is on Raspberry PI OS Lite (64-bit) (basically Debian), and the PC is Debian.

Not really specific to Julia:

You need to give both devices an IP address (and a network mask) first, and check that they can mutually ping each other.

For example, you could choose to use the subnet 192.168.80.0/24, and then assign 192.168.80.1 to the PC and 192.168.80.2 to the PI.

If you use a spare second Ethernet device on your PC, and it is e.g. called eth1, then run on the PC

$ sudo ip addr add 192.168.80.1/24 dev eth1

and on the PI run something like

$ sudo ip addr add 192.168.80.2/24 dev eth0

and now both will have their local IPv4 address configured on the same private RFC 1918 class C network.

Note that such manual IP address configuration via ip addr is a temporary setting, which will not survive the next reboot. For a persistent setting, you can use network-manager, or netplan, or ifup or whatever network configuration tool you prefer or your OS currently uses (there are probably too many).

For extra credit: use an IPv6 link-local address (they look like fe80::1234%eth0) or an IPv6 ULA, or set up a DHCPv4 or DHCPv6 or NDP/SLAAC server.

1 Like

I have used dnsmasq running on the Pi to set this up before. Configure dnsmasq DHCP serving and ensure that it runs on startup. Then, when you plug your laptop in to the Pi, it will be assigned a DHCP address by the Pi. For name resolution, MDNS is easier to get working than using the DNS server in dnsmasq. Configure the Pi to advertise itself over mdns and ensure your laptop resolves by mdns and you should be able to connect to the Pi at hostname.local

If you do set this up, be careful of plugging the Pi into someone else’s network as it will compete with the DHCP server on that network and likely assign addresses to machines that it shouldn’t causing mysterious loss of connectivity for computers you didn’t even know about.

1 Like

Wow that sounds like it would work with any computer I’ll plug that ethernet cable to! The dream would be for this to work with any laptop. The user would install the client side program, plug in the cable, and magic…

Thank you both! I’m starting with @mgkuhn initial suggestion with ip addr.

Success! From the PC:

yakir@luna:~$ ping 192.168.80.2
PING 192.168.80.2 (192.168.80.2) 56(84) bytes of data.
64 bytes from 192.168.80.2: icmp_seq=1 ttl=64 time=0.396 ms
64 bytes from 192.168.80.2: icmp_seq=2 ttl=64 time=0.266 ms
64 bytes from 192.168.80.2: icmp_seq=3 ttl=64 time=0.264 ms
^C

and

yakir@luna:~$ ssh 192.168.80.2

yakir@raspberrypi:~ $ ping 192.168.80.1
PING 192.168.80.1 (192.168.80.1) 56(84) bytes of data.
64 bytes from 192.168.80.1: icmp_seq=1 ttl=64 time=0.320 ms
64 bytes from 192.168.80.1: icmp_seq=2 ttl=64 time=0.347 ms
64 bytes from 192.168.80.1: icmp_seq=3 ttl=64 time=0.821 ms

But what IP address (and port) do I put in:

server = WebSockets.listen!("<some IP address>", 8081) do ws
...

I blindly tried 192.168.80.0-3 with a variation of ports, but I keep getting

ERROR: cannot bind to port; may already be in use or access denied
Stacktrace:
  [1] error(s::String)
    @ Base ./error.jl:35
  [2] #listen#10
    @ ~/.julia/juliaup/julia-1.9.2+0.aarch64.linux.gnu/share/julia/stdlib/v1.9/Sockets/src/Sockets.jl:620 [inlined]
  [3] listen
    @ ~/.julia/juliaup/julia-1.9.2+0.aarch64.linux.gnu/share/julia/stdlib/v1.9/Sockets/src/Sockets.jl:618 [inlined]
  [4] HTTP.Servers.Listener(addr::Sockets.InetAddr{Sockets.IPv4}, host::String, port::String; sslconfig::Nothing, reuseaddr::Bool, backlog::Int64, server::Nothing, listenany::Bool, kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ HTTP.Servers ~/.julia/packages/HTTP/nn2yB/src/Servers.jl:69
  [5] Listener
    @ ~/.julia/packages/HTTP/nn2yB/src/Servers.jl:39 [inlined]
  [6] HTTP.Servers.Listener(host::String, port::Int64; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ HTTP.Servers ~/.julia/packages/HTTP/nn2yB/src/Servers.jl:74
  [7] Listener
    @ ~/.julia/packages/HTTP/nn2yB/src/Servers.jl:74 [inlined]
  [8] #listen!#7
    @ ~/.julia/packages/HTTP/nn2yB/src/Servers.jl:313 [inlined]
  [9] listen!(::Function, ::String, ::Int64)
    @ HTTP.Servers ~/.julia/packages/HTTP/nn2yB/src/Servers.jl:313
 [10] listen!(::Function, ::String, ::Vararg{Any}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ HTTP.WebSockets ~/.julia/packages/HTTP/nn2yB/src/WebSockets.jl:417
 [11] listen!(::Function, ::String, ::Vararg{Any})
    @ HTTP.WebSockets ~/.julia/packages/HTTP/nn2yB/src/WebSockets.jl:417
 [12] top-level scope
    @ REPL[3]:1

I don’t know about WebSockets, but for normal TCP sockets, you can put in 0.0.0.0 as the address on which you listen, to listen to any incoming IPv4 destination address, or ::0 to listen to any incoming connection requests addressed to any IPv4 or IPv6 address. But you can also put in the address on which the other side tries to reach the listening server, here 192.168.80.2.

Regarding the “may already be in use” message: When listening on a TCP socket, be careful not to reopen them too quickly after closing them. After you have properly closed a TCP port, it lingers for a couple of minutes in a reserved state to make sure any stray packets from that connection have been received and aren’t able to accidentally reopen the connection or interfere with the next session.

Also, in interactive environments like the Julia REPL, it is easy to forget to properly release a resource by closing it, and then you might also get an “in use” error. Best terminate the process (quit Julia) and wait a few minutes before retrying to listen on the same port.

1 Like

Worked! Thank a lot Markus!

I’ll slowly work on implementing @contradict’s dnsmasq solution later next week, but for now this is awesome.