web-dev-qa-db-fra.com

Quelle est la différence entre socket.send () et socket.sendall ()?

Je suis confus à propos des fonctions socket.send() et socket.sendall() en Python. D'après ce que j'ai compris de la documentationsend() la fonction utilise TCP et la fonction sendall()) utilise le protocole UDP pour l'envoi de données. I Sachez que TCP est plus fiable pour la plupart des applications Web car nous pouvons vérifier quels paquets sont envoyés et lesquels ne le sont pas. C’est pourquoi, je pense que l’utilisation de send() fonction peut être plus fiable que la fonction sendall().

À ce stade, je voudrais demander quelle est la différence exacte entre ces deux fonctions et laquelle est la plus fiable pour les applications Web?

Merci.

28
cengineer

socket.send est une méthode de bas niveau et se résume à la méthode C/syscall send (3) / send (2) . Il peut envoyer moins d'octets que ce que vous avez demandé, mais renvoie le nombre d'octets envoyés.

socket.sendall est une méthode de haut niveau réservée à Python qui envoie la totalité du tampon que vous avez transmis ou lève une exception. Il le fait en appelant socket.send jusqu'à ce que tout soit envoyé ou qu'une erreur se produise.

Si vous utilisez TCP avec des sockets bloquants et que vous ne voulez pas être dérangé par des éléments internes (c'est le cas pour la plupart des applications réseau simples), utilisez sendall.

Et python docs:

Contrairement à send (), cette méthode continue à envoyer les données d'une chaîne jusqu'à ce que toutes les données aient été envoyées ou qu'une erreur se produise. Aucun n'est retourné en cas de succès. En cas d'erreur, une exception est déclenchée et il n'y a aucun moyen de déterminer combien de données , le cas échéant, ont été envoyées avec succès

Crédits à Philipp Hagemeister pour une brève description que j'ai eu dans le passé.

modifier

sendall utiliser sous le capot send - jetez un oeil à la mise en œuvre de cpython . Voici un exemple de fonction agissant (plus ou moins) comme sendall:

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

ou de rpython (source 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()
49
kwarunek