¿Cuál es la diferencia entre socket.send () y socket.sendall ()?

Estoy confundido acerca de las socket.send() y socket.sendall() en Python. Como entiendo por la documentación, la función send() usa el protocolo TCP y la función sendall() usa el protocolo UDP para enviar datos. Sé que TCP es más confiable para la mayoría de las aplicaciones web porque podemos verificar qué paquetes se envían y cuáles no. Por eso, creo que el uso de la función send() puede ser más confiable que la función sendall() .

En este punto, quiero preguntar cuál es la diferencia exacta entre estas dos funciones y cuál es la más confiable para las aplicaciones web.

Gracias.

socket.send es un método de bajo nivel y básicamente solo el método C / syscall send (3) / send (2) . Puede enviar menos bytes de los que solicitó, pero devuelve el número de bytes enviados.

socket.sendall es un método de alto nivel solo para Python que envía todo el búfer que pasa o lanza una excepción. Lo hace llamando a socket.send hasta que todo haya sido enviado o se produzca un error.

Si está utilizando TCP con sockets de locking y no quiere que le molesten los elementos internos (este es el caso de la mayoría de las aplicaciones de red simples), use sendall.

Y los documentos de Python:

A diferencia de enviar (), este método continúa enviando datos desde la cadena hasta que se envían todos los datos o se produce un error. Ninguno es devuelto en el éxito. En caso de error, se genera una excepción y no hay manera de determinar cuántos datos , si los hay, se enviaron con éxito

Créditos a Philipp Hagemeister por una breve descripción que obtuve en el pasado.

editar

sendall use under the hood send – eche un vistazo a la implementación de cpython . Aquí está la función de muestra que actúa (más o menos) como 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 de rpython (fuente pypy) :

 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() 

Como dice el documento que ya ha mencionado, send () es para TCP y sendall () es para UDP .

Para comprender la diferencia entre estas dos funciones, solo tiene que saber la diferencia entre TCP y UDP ; lo que significa que send () realiza un seguimiento del número de bytes enviados al destino (servidor), y su instrucción finaliza con éxito solo cuando se recibe todo el tamaño de búfer en el servidor, para hacerlo, el cliente debe conectarse al servidor para tener el información sobre los ACKs.

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

En el caso de sendall () , simplemente envía el búfer a un destino (servidor) sin tener la información de si este búfer es recibido realmente por el servidor o no.

 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)) 

Espero que ayude !