abroskiboiii
abroskiboiii

Reputation: 31

Connecting 2 devices on different networks using Python Sockets

So if there is a client and server with their respective dynamic IPv4 addresses, and both are connected to the internet via 2 separate routers, how do I get the client and server to connect with each other using their dynamic IPv4 addresses and the router's static IPv4 address in Python 3.

I am pretty new to networking in general so if there is another standard method for doing this please suggest a better method below.

I currently have this code for the client side and the server side.

Client:

import socket
import tqdm
import os

SEPARATOR = "<SEPARATOR>"
BUFFER_SIZE = 4096 # send 4096 bytes each time step

# the ip address or hostname of the server, the receiver
host = "192.168.1.21"
# the port, let's use 5001
port = 20
# the name of file we want to send, make sure it exists
filename = ""
# get the file size
filesize = os.path.getsize(filename)

# create the client socket
s = socket.socket()

print(f"[+] Connecting to {host}:{port}")
s.connect((host, port))
print("[+] Connected.")

# send the filename and filesize
s.send(f"{filename}{SEPARATOR}{filesize}".encode())

# start sending the file
progress = tqdm.tqdm(range(filesize), f"Sending {filename}", unit="B", unit_scale=True, unit_divisor=1024)
with open(filename, "rb") as f:
    while True:
        # read the bytes from the file
        bytes_read = f.read(BUFFER_SIZE)
        if not bytes_read:
            # file transmitting is done
            break
        # we use sendall to assure transimission in 
        # busy networks
        s.sendall(bytes_read)
        # update the progress bar
        progress.update(len(bytes_read))
# close the socket
s.close()

Server:

import socket
import tqdm
import os
from pathlib import Path
# device's IP address
SERVER_HOST = "0.0.0.0"
SERVER_PORT = 5001
# receive 4096 bytes each time
BUFFER_SIZE = 4096
SEPARATOR = "<SEPARATOR>"

# create the server socket
# TCP socket
s = socket.socket()

# bind the socket to our local address
s.bind((SERVER_HOST, SERVER_PORT))

# enabling our server to accept connections
# 5 here is the number of unaccepted connections that
# the system will allow before refusing new connections
s.listen(5)
print(f"[*] Listening as {SERVER_HOST}:{SERVER_PORT}")

# accept connection if there is any
client_socket, address = s.accept()
# if below code is executed, that means the sender is connected
print(f"[+] {address} is connected.")

# receive the file infos
# receive using client socket, not server socket
received = client_socket.recv(BUFFER_SIZE).decode()
filename, filesize = received.split(SEPARATOR)
# remove absolute path if there is
filename = os.path.basename(filename)
# convert to integer
filesize = int(filesize)

# start receiving the file from the socket
# and writing to the file stream
progress = tqdm.tqdm(range(filesize), f"Receiving {filename}", unit="B", unit_scale=True, unit_divisor=1024)
home = str(Path.home())
with open(f"{home}/Downloads/{filename}", "wb") as f:
   while True:
       # read 1024 bytes from the socket (receive)
       bytes_read = client_socket.recv(BUFFER_SIZE)
       if not bytes_read:
           # nothing is received
           # file transmitting is done
           break
       # write to the file the bytes we just received
       f.write(bytes_read)
       # update the progress bar
       progress.update(len(bytes_read))

# close the client socket
client_socket.close()
# close the server socket
s.close()

Note: The above client and server code was not written by me. It was copied from another website and gently modified.

Website link: https://www.thepythoncode.com/article/send-receive-files-using-sockets-python

Upvotes: 3

Views: 1248

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 598001

The client will not be able to connect directly to the server when they are on different networks.

The router on the server side must be configured to enable port forwarding of inbound traffic from the router's WAN IP/port to the server's LAN IP/port. The server can then listen for connections on its LAN IP/port, and the client can connect to the server router's WAN IP/port.

Port forwarding must be handled in the router's configuration. Typically, that is done by an admin manually. However, if the router supports (and has enabled) UPnP, the server can setup the port forwarding dynamically from its own code using the Internet Gateway Device protocol. Some platforms provide APIs which implement that protocol for you (for example, Microsoft's NATUPNPLib and Firewall APIs on Windows).

Upvotes: 1

Related Questions