Пробивание отверстий Python NAT между сервером и большим количеством клиентов

#python #python-3.x #python-sockets

Вопрос:

В моем проекте python мне нужно создать tcp-туннель между несколькими клиентами и одним сервером на определенном порту. Я начинаю писать серверный код:

server.py

 import threading
import socket

MY_AS_SERVER_PORT = 61591

TIMEOUT = 120.0
BUFFER_SIZE = 4096


def get_my_local_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # doesn't even have to be reachable
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]
    except Exception:
        IP = '127.0.0.1'
    finally:
        s.close()
    return bytes(IP, encoding='utf-8')


def wait_for_msg(new_connection, client_address):
    while True:
        try:
            packet = new_connection.recv(BUFFER_SIZE)
            if packet:
                msg_from_client = packet.decode('utf-8')
                client_connected_from_ip = client_address[0]
                client_connected_from_port = client_address[1]

                print("We have a plutonix node. Node advertised his local IP as:", msg_from_client)
                print(f"Although, our connection is from: [{client_connected_from_ip}]:{client_connected_from_port}")

                msg_back = bytes("SERVER registered your data. Your local IP is: "   str(msg_from_client)   " You are connecting to the server FROM: "   str(client_connected_from_ip)   ":"   str(client_connected_from_port), encoding='utf-8')
                new_connection.sendall(msg_back)
                break

        except ConnectionResetError:
            break

        except OSError:
            break


def server():
    sock = socket.socket()

    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

    sock.bind((get_my_local_ip().decode('utf-8'), MY_AS_SERVER_PORT))
    sock.listen(8)
    sock.settimeout(TIMEOUT)
    while True:
        try:
            new_connection, client_address = sock.accept()

            if new_connection:
                threading.Thread(target=wait_for_msg, args=(new_connection,client_address,)).start()
                msg = bytes("Greetings! This message came from SERVER as message back!", encoding='utf-8')
                new_connection.sendall(msg)
        except socket.timeout:
            pass


if __name__ == '__main__':
    server()
 

поэтому я пишу также клиентский код:

client.py

 import socket
import time
import threading

SERVER_IP = '61.99.41.30'
SERVER_PORT = 61591
# At the moment We don't want to establish a connection with a static port. Let the OS pick a random empty one.
# TODO: Check if in future we need static sub-port for all nodes
# MY_AS_NODE_PORT = 8510

TIMEOUT = 3
BUFFER_SIZE = 4096


def get_my_local_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # doesn't even have to be reachable
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]
    except Exception:
        IP = '127.0.0.1'
    finally:
        s.close()
    return bytes(IP, encoding='utf-8')


def constantly_try_to_connect(sock):
    while True:
        try:
            sock.connect((SERVER_IP, SERVER_PORT))
        except ConnectionRefusedError:
            print(f"Can't connect to the SERVER IP [{SERVER_IP}]:{SERVER_PORT} - does the server alive? Sleeping for a while...")
            time.sleep(1)
        except OSError:
            # print("Already connected to the server. Kill current session to reconnect...")
            pass


def client():
    sock = socket.socket()

    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

    # sock.bind((get_my_local_ip().decode('utf-8'), MY_AS_NODE_PORT))
    sock.settimeout(TIMEOUT)

    threading.Thread(target=constantly_try_to_connect, args=(sock,)).start()

    while True:
        try:
            packet = sock.recv(BUFFER_SIZE)

            if packet:
                print(packet)
                sock.sendall(get_my_local_ip())

        except OSError:
            pass


if __name__ == '__main__':
    client()
 

well, at this point i run on background on my server the code and from two different clients in another network i run the client.py code on client1 and i get:

enter image description here

well! if now i check on my server using ss command connection i get:

enter image description here

ok, now i run the client.py code also from the second client ad i get a succefful connection message:

enter image description here

but if i run ss command again on server i see:

enter image description here

Why there isn’t both connection on my server?
I would to have for example:

 192.168.1.20:61591    178.19.148.49:65486
192.168.1.20:61591    178.19.148.49:22992
 

why last connection overcome on server connection data?
How is possible connect multiple clients on my server using different ports?

So many thanks in advance