Как бороться с сокетом NAT python - PullRequest
0 голосов
/ 14 апреля 2020

Я пытаюсь создать приложение, которое будет доступно широкому кругу пользователей. Это некоторые базовые c сокеты + python сетевые штучки. Недавно я немного исследовал и попробовал несколько вещей. Я реализовал некоторые вещи UPNP через miniupnp c, но дело в том, что вам нужно разрешение на использование UPNP на большинстве маршрутизаторов, что не идеально подходит для моих нужд. Я пытаюсь полностью обойти такие вещи, как переадресация портов. Я также попытался полностью переключиться с сокета Python на pyp2p, но не смог заставить его работать из-за отсутствия документации и обслуживания проекта.

Есть ли простой способ обойти NAT, и если да, то как?

Клиент:

import socket
import struct
import os
import pickle
from pygame import mixer


def connect(host, port):
    ourmusic = []
    fileBRAIN = []
    musicPath = './music'

   s = socket.socket()
   print('created socket')
   s.connect((host,port))
   print('conected to ',host)

   #identify self
   hostname = socket.gethostname()    
   IPAddr = socket.gethostbyname(hostname)    
   IPAddrBYTE = str(IPAddr).encode('utf-8')
   send_msg(s, IPAddrBYTE)

   if os.path.exists(str(host)) == True :
        print('server seen previously')

        #load host's song list
        fileBRAIN = pickle.load(open( str(host), 'rb'))

        #recieve new files from host
        receiveFiles(s, fileBRAIN)

        #compare files
        saveMusicList(ourmusic, musicPath)
        filesToTransmit = diff(ourmusic, fileBRAIN)

        #transmit music which host dont have
        transmitFiles(s , filesToTransmit, fileBRAIN)

        #save host's song list
        pickle.dump(fileBRAIN, open(str(host), 'wb'))

        #start playing music
        clientMainLoop(s)

else: 
        print('server not seen previously')

        #recieve music files from host
        receiveFiles(s, fileBRAIN)

        #compare files
        saveMusicList(ourmusic, musicPath)
        filesToTransmit = diff(ourmusic, fileBRAIN)

        #transmit music which host dont have
        transmitFiles(s , filesToTransmit, fileBRAIN)

        #save host's song list
        pickle.dump(fileBRAIN, open(str(host), 'wb'))

        #start playing music
        clientMainLoop(s)

def clientMainLoop(socket):
    mixer.init()
    while True:
        randomsongBYTE = recv_msg(socket)
        randomsong = randomsongBYTE.decode('utf-8')


        mixer.music.load('./music/' + randomsong)
        mixer.music.play()
        print('now playing: ' + randomsong)

        while mixer.music.get_busy() == True:
           temp = 0
        else:
            print('music ended receiving next...')

    def transmitFiles(socket, files, fileBRAIN):
          Transmissions = struct.pack('i',len(files))
          send_msg(socket, Transmissions) 

          for x in files:
                filename = str(x).encode('utf-8') 
                send_msg(socket, filename)

                file = open('./music/' + x , 'rb')
                file_data = file.read()
                send_msg(socket, file_data) 

                fileBRAIN.append(str(x))
                print(x + '\n' + 'has been send transmitted successfully')
                print('')

  def receiveFiles(s, fileBRAIN):            
       i = 1

    transmissionsDATA = recv_msg(s) 
    transmissionsTUP = struct.unpack('i',transmissionsDATA)
    transmissions = transmissionsTUP[0]
    print('there are ' + str(transmissions) + ' awaiting  receive 
         transmissions')

while i <= transmissions:
    BYTEfilename = recv_msg(s)
    filename = BYTEfilename.decode('utf-8')

    file = open('./music/' + filename, 'wb')
    file_data = recv_msg(s) 
    file.write(file_data)
    file.close()

    fileBRAIN.append(str(filename))
    print('transmission ' + str(i) + ' recieived')
    i = i + 1


def saveMusicList(musiclist, musicPath):
    for entry in os.listdir(musicPath):
            if os.path.isfile(os.path.join(musicPath, entry)):
                    musiclist.append(entry)

#find elements which are not in the other list                        
def diff(li1, li2): 
     return (list(set(li1) - set(li2)))         

#TCP msg protocoll

def send_msg(sock, msg):
    # Prefix each message with a 4-byte length (network byte order)
    msg = struct.pack('>I', len(msg)) + msg
    sock.sendall(msg)

def recv_msg(sock):
    # Read message length and unpack it into an integer
    raw_msglen = recvall(sock, 4)
    if not raw_msglen:
       return None
    msglen = struct.unpack('>I', raw_msglen)[0]
    # Read the message data
    return recvall(sock, msglen)

def recvall(sock, n):
    # Helper function to recv n bytes or return None if EOF is hit
    data = bytearray()
    while len(data) < n:
        packet = sock.recv(n - len(data))
        if not packet:
            return None
        data.extend(packet)
    return data

Сервер:

import socket
import os
import struct
import pickle
import miniupnpc
from random import randint
from pygame import mixer



def init(port):
    fileBRAIN = []
    ourmusic = []        
    files = []
    musicPath = './music'

    try:
            #Network Gateway (port forwarding)
            upnp = miniupnpc.UPnP()

            upnp.discoverdelay = 10
            upnp.discover()

            upnp.selectigd()

            upnp.addportmapping(port, 'TCP', upnp.lanaddr, port, 
            'OpenMCS', '')

    except:
            print('INFO:Port is already forwarded or you dont have the 
            premission to forward it')



    s = socket.socket()
    host = ('') #socket.gethostname()
    s.bind((host,port))
    s.listen(5)
    print(host)
    print('waiting for any incoming conections ... ')

    conn,addr = s.accept()

    #get client identity
    ClientIPAddrBYTE = recv_msg(conn)
    ClientIPAddr = ClientIPAddrBYTE.decode('utf-8')

    if os.path.exists(ClientIPAddr) == True :
            print('client seen previously')

            #load client's song list
            fileBRAIN = pickle.load(open( ClientIPAddr, 'rb'))

            #compare files
            saveMusicList(ourmusic, musicPath)
            filesToTransmit = diff(ourmusic, fileBRAIN)

            #transmit new files client doesn't have
            transmitFiles(conn, filesToTransmit, fileBRAIN)

            #recieve music files we dont have
            receiveFiles(conn, fileBRAIN)

            #save client's song list
            pickle.dump(fileBRAIN, open(ClientIPAddr, 'wb'))

            #start playing music
            serverMainLoop(conn, ourmusic, musicPath)

    else: 
            print('client not seen previously')

            #transmit own music files to client
            transmitFiles(conn, files, fileBRAIN)

            #recieve music files we dont have
            receiveFiles(conn, fileBRAIN)

            #save client's song list
            pickle.dump(fileBRAIN, open(ClientIPAddr, 'wb'))

            #start playing music
            serverMainLoop(conn, ourmusic, musicPath)


    def serverMainLoop(socket, ourmusic, musicPath):
         saveMusicList(ourmusic, musicPath)
         mixer.init()
         while True:
            randomsong = ourmusic[randint(0, (len(ourmusic) - 1 ))]
            randomsongBYTE = randomsong.encode('utf-8')
            send_msg(socket, randomsongBYTE)

            mixer.music.load('./music/' + randomsong)
            mixer.music.play()
            print('now playing: ' + randomsong)

            while mixer.music.get_busy() == True:
                temp = 0
            else:
                    print('music ended picking next...')

def transmitFiles(socket, files, fileBRAIN):
    Transmissions = struct.pack('i',len(files))
    send_msg(socket, Transmissions) 

    for x in files:
            filename = str(x).encode('utf-8') 
            send_msg(socket, filename)

            file = open('./music/' + x , 'rb')
            file_data = file.read()
            send_msg(socket, file_data) 

            fileBRAIN.append(str(x))
            print(x + '\n' + 'has been send transmitted successfully')
            print('')

def receiveFiles(s, fileBRAIN):            
    i = 1

    transmissionsDATA = recv_msg(s) 
    transmissionsTUP = struct.unpack('i',transmissionsDATA)
    transmissions = transmissionsTUP[0]
    print('there are ' + str(transmissions) + ' awaiting receive 
    transmissions')

    while i <= transmissions:
         BYTEfilename = recv_msg(s)
         filename = BYTEfilename.decode('utf-8')

         file = open('./music/' + filename, 'wb')
         file_data = recv_msg(s) 
         file.write(file_data)
         file.close()

         fileBRAIN.append(str(filename))
         print('transmission ' + str(i) + ' recieved')
    i = i + 1


def saveMusicList(musiclist, musicPath):
    for entry in os.listdir(musicPath):
            if os.path.isfile(os.path.join(musicPath, entry)):
                    musiclist.append(entry)

#find elements which are not in the other list
def diff(li1, li2): 
    return (list(set(li1) - set(li2)))                 


#TCP msg proctocoll

def send_msg(sock, msg):
    # Prefix each message with a 4-byte length (network byte order)
    msg = struct.pack('>I', len(msg)) + msg
    sock.sendall(msg)

def recv_msg(sock):
     # Read message length and unpack it into an integer
     raw_msglen = recvall(sock, 4)
     if not raw_msglen:
         return None
     msglen = struct.unpack('>I', raw_msglen)[0]
     # Read the message data
     return recvall(sock, msglen)

def recvall(sock, n):
     # Helper function to recv n bytes or return None if EOF is hit
     data = bytearray()
    while len(data) < n:
        packet = sock.recv(n - len(data))
        if not packet:
           return None
        data.extend(packet)
    return data

Полный код можно найти здесь, если вам это нужно: https://github.com/Finn1510/OpenMCS

...