socket.send()和socket.sendall()的区别是什么?

90
我对Python中的socket.send()socket.sendall()函数感到困惑。根据文档,我理解send()函数使用TCP协议,而sendall()函数则使用UDP协议发送数据。我知道对于大多数Web应用程序来说,TCP更可靠,因为可以检查哪些数据包已发送,哪些数据包未发送。因此,我认为使用send()函数可能比sendall()函数更可靠。
在这一点上,我想问一下两个函数的确切区别是什么,哪一个更适合Web应用程序?
谢谢。

4
文档说明很清楚,我认为 - .send() 可能不会发送您提供的所有数据,而 sendall() 不会返回,直到所有数据都已发送 - 但这可能需要更长时间。一般来说,除非您知道需要使用 .send(),否则应该使用 sendall() - Tom Dalton
1个回答

148

socket.send 是一个低级方法,基本上只是 C/syscall 方法 send(3) / send(2)。它可以发送少于你请求的字节数,但会返回发送的字节数。

socket.sendall 是一个高级 Python-only 方法,它发送传递给它的整个缓冲区或抛出异常。它通过调用 socket.send 直到所有数据被发送或发生错误来实现。

如果您正在使用阻塞套接字的 TCP 并且不想被内部问题所困扰(这通常是大多数简单网络应用程序的情况),请使用 sendall。

Python 文档如下:

与 send() 不同,此方法继续从字符串发送数据,直到所有数据已发送或发生错误。成功时返回 None。在发生错误时,会引发异常,并且无法确定有多少数据已成功发送

感谢 Philipp Hagemeister 过去提供的简要描述。

编辑

sendall 在底层使用 send - 查看 cpython 实现。这里是一个类似于 sendall 的示例函数:

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

或从rpython (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()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接