real - socket sock_stream python




Python Socket riceve una grande quantità di dati (4)

Quando provo a ricevere grandi quantità di dati, viene troncato e devo premere Invio per ottenere il resto dei dati. All'inizio sono stato in grado di aumentarlo un po ', ma non lo riceverà ancora. Come puoi vedere, ho aumentato il buffer su conn.recv () ma non ottiene ancora tutti i dati. Lo interrompe ad un certo punto. Devo premere Invio sul mio raw_input per ricevere il resto dei dati. Posso comunque ottenere tutti i dati contemporaneamente? Ecco il codice.

port = 7777
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('0.0.0.0', port))
sock.listen(1)
print ("Listening on port: "+str(port))
while 1:
    conn, sock_addr = sock.accept()
    print "accepted connection from", sock_addr
    while 1:
        command = raw_input('shell> ')
            conn.send(command)
                data = conn.recv(8000)
                if not data: break
                print data,
    conn.close()

La risposta accettata va bene, ma sarà molto lento con i file di grandi dimensioni. La stringa è una classe immutabile, questo significa che più oggetti devono essere creati ogni volta che si utilizza il segno + , usando l' list come una struttura dello stack più efficiente.

Questo dovrebbe funzionare meglio

while True: 
    chunck = s.recv(10000)
    if not chunck: 
        break
    fragments.append(chunck)

print "".join(fragments)

Modifica del codice di Adam Rosenfield:

import sys


def send_msg(sock, msg):
    size_of_package = sys.getsizeof(msg)
    package = str(size_of_package)+":"+ msg #Create our package size,":",message
    sock.sendall(package)

def recv_msg(sock):
    try:
        header = sock.recv(2)#Magic, small number to begin with.
        while ":" not in header:
            header += sock.recv(2) #Keep looping, picking up two bytes each time

        size_of_package, separator, message_fragment = header.partition(":")
        message = sock.recv(int(size_of_package))
        full_message = message_fragment + message
        return full_message

    except OverflowError:
        return "OverflowError."
    except:
        print "Unexpected error:", sys.exc_info()[0]
        raise

Tuttavia, incoraggerei fortemente l'utilizzo dell'approccio originale.


Puoi usarlo come: data = recvall(sock)

def recvall(sock):
    BUFF_SIZE = 4096 # 4 KiB
    data = b''
    while True:
        part = sock.recv(BUFF_SIZE)
        data += part
        if len(part) < BUFF_SIZE:
            # either 0 or end of data
            break
    return data

TCP / IP è un protocollo basato sul flusso , non un protocollo basato su messaggi . Non vi è alcuna garanzia che ogni chiamata send() di un peer abbia come risultato una singola chiamata recv() dall'altro peer che riceve i dati esatti inviati - potrebbe ricevere i dati pezzo-pasto, divisi tra più chiamate recv() , a causa del pacchetto la frammentazione.

È necessario definire il proprio protocollo basato su messaggi su TCP per differenziare i limiti dei messaggi. Quindi, per leggere un messaggio, si continua a chiamare recv() fino a quando non si legge un intero messaggio o si verifica un errore.

Un modo semplice per inviare un messaggio è precedere ogni messaggio con la sua lunghezza. Quindi per leggere un messaggio, prima leggi la lunghezza, poi leggi molti byte. Ecco come potresti farlo:

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 = b''
    while len(data) < n:
        packet = sock.recv(n - len(data))
        if not packet:
            return None
        data += packet
    return data

Quindi è possibile utilizzare le funzioni send_msg e recv_msg per inviare e ricevere messaggi interi e non avranno alcun problema con i pacchetti divisi o coalescati a livello di rete.







sockets