2015-12-13 18 views
10

Sono un po 'confuso riguardo le funzioni socket.send() e socket.sendall() in Python. Come ho capito dalla funzione send() the documentation, le regole TCP e la funzione sendall() applicano le regole UDP per l'invio di dati al socket. E so anche che TCP è più affidabile per la maggior parte delle applicazioni Web perché possiamo controllare quali pacchetti vengono inviati e quali pacchetti non lo sono. Ecco perché, penso che l'uso della funzione send() possa essere più affidabile piuttosto che la funzione sendall() ma non ne sono sicuro. A questo punto, voglio chiedere qual è la differenza esatta tra queste due funzioni e quale è più affidabile per le applicazioni web?Qual è la differenza tra socket.send() e socket.sendall()?

Grazie.

+1

La documentazione è abbastanza chiara IMO - '.send()' potrebbe non inviare tutti i dati che gli vengono dati, mentre 'sendall()' non ritornerà finché non saranno stati inviati tutti i dati - ma questo potrebbe richiedere più tempo. In generale si dovrebbe usare 'sendall()' a meno che non si sappia che è necessario usare '.send()'. –

risposta

19

socket.send è un metodo di basso livello e in pratica solo il metodo C/syscall send(3)/send(2). Può inviare meno byte di quanto richiesto, ma restituisce il numero di byte inviati.

socket.sendall è un metodo di alto livello solo Python che invia l'intero buffer passato o genera un'eccezione. Lo fa chiamando socket.send fino a quando tutto è stato inviato o si verifica un errore.

Se si utilizza TCP con zoccoli di blocco e non si vuole essere disturbati da interni (questo è il caso per la maggior parte delle semplici applicazioni di rete), utilizza sendall.

e Python docs:

differenza send(), questo metodo continua a inviare i dati da stringa fino sia tutti i dati sono stati inviati o si verifica un errore. Nessuno viene restituito al successo . In caso di errore, viene sollevata un'eccezione, e non v'è alcun modo per determinare la quantità di dati, se del caso, è stato inviato con successo

Crediti Philipp Hagemeister per breve descrizione ho avuto in passato.

modificare

sendall uso sotto il cofano send - date un'occhiata su cpython attuazione. Ecco funzione di esempio agendo (più o meno) come sendall:

def sendall(sock, data, flags=0): 
    ret = sock.send(data, flags) 
    if ret > 0: 
     return sendall(sock, data[ret:], flags) 
    else: 
     return None 

o da rpython (pypy source):

def sendall(self, data, flags=0, signal_checker=None): 
    """Send a data string to the socket. For the optional flags 
    argument, see the Unix manual. This calls send() repeatedly 
    until all data is sent. If an error occurs, it's impossible 
    to tell how much data has been sent.""" 
    with rffi.scoped_nonmovingbuffer(data) as dataptr: 
     remaining = len(data) 
     p = dataptr 
     while remaining > 0: 
      try: 
       res = self.send_raw(p, remaining, flags) 
       p = rffi.ptradd(p, res) 
       remaining -= res 
      except CSocketError, e: 
       if e.errno != _c.EINTR: 
        raise 
      if signal_checker is not None: 
       signal_checker() 
+0

Grazie. Ho capito il punto. – cengineer

-7

Come il doc che si è già accennato, dice, send() è per TCP e sendall() è per UDP.

Per capire la differenza tra queste due funzioni, basta conoscere la differenza tra TCP et UDP; significa che send() tiene traccia del numero di byte inviati alla destinazione (server) e la sua istruzione termina con successo solo quando tutto il buffer_size viene ricevuto come server, per fare in modo che il client abbia bisogno di connettersi al server per avere le informazioni sugli ACK.

BUFFER = "a string" 
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.connect((target_host, target_port)) 
client.send(BUFFER) 

Nel caso di sendall(), semplicemente invia il buffer a un (server) di destinazione senza avere le informazioni se questo buffer è davvero ricevuto dal server o meno.

BUFFER = "a string" 
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
sock.connect((target_host, target_port)) 
client.sendall(BUFFER, (target_host, target_port)) 

speranza che aiuta!

+0

Questa spiegazione è stata molto utile. Grazie Mr.Mohammed. Stavo conoscendo il TCP e l'UDP ma ero confuso riguardo a send() e sendall(). Ho capito grazie! – cengineer

+0

Felice di sentire che @MehmetAKALIN 8-) – MrHanachoo

+2

Questo in realtà non è vero. send vs sendall non è TCP vs UDP. Inoltre 'send' non garantisce che il buffer sia inviato,' Restituisce il numero di byte inviati. Le applicazioni sono responsabili di controllare che tutti i dati siano stati inviati; se solo alcuni dei dati sono stati trasmessi, l'applicazione deve tentare la consegna dei dati rimanenti » – kwarunek

Problemi correlati