Подтвердить что ты не робот

В чем разница между socket.send() и socket.sendall()?

Я немного запутался в функциях socket.send() и socket.sendall() в Python. Как я понимаю из в функции документации send() применяется правила TCP, а функция sendall() применяет правила UDP для отправки данных в сокет. Кроме того, я знаю, что TCP более надежный для большинства веб-приложений, потому что мы можем проверить, какие пакеты отправляются и какие пакеты нет. Поэтому я думаю, что функция send() может быть более надежной, чем функция sendall(), но я не уверен. На этом этапе я хочу спросить, какая именно разница между этими двумя функциями и какая из них более надежна для веб-приложений?

Спасибо.

4b9b3361

Ответ 1

socket.send - это низкоуровневый метод и в основном просто метод C/syscall send (3)/отправить (2). Он может отправлять меньше байтов, чем вы запрашивали, но возвращает количество отправленных байтов.

socket.sendall - это высокоуровневый метод Python, который отправляет весь буфер, который вы передаете или генерирует исключение. Он делает это, вызывая socket.send до тех пор, пока все не будет отправлено или не произойдет ошибка.

Если вы используете TCP с блокирующими сокетами и не хотите беспокоиться внутренними (это относится к большинству простых сетевых приложений), использование sendall.

И документы python:

В отличие от send() этот метод продолжает отправлять данные из строки до тех пор, пока либо все данные были отправлены, либо возникла ошибка. Ничего не возвращается успех. При ошибке генерируется исключение, а нет способа определить, сколько данных, если таковые имеются, было успешно отправлено

Кредиты для Филиппа Хагмайстера для краткого описания Я получил в прошлом.

изменить

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

Ответ 2

Как уже упоминалось в документе, send() для TCP и sendall() для UDP.

Чтобы понять разницу между этими двумя функциями, вам нужно только знать разницу между TCP et UDP; что send() отслеживает количество байтов, отправленных на целевой (сервер), и его команда заканчивается с успехом только тогда, когда весь buffer_size получен моим сервером, для этого клиенту необходимо подключитесь к серверу, чтобы получить информацию о ACK.

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

В случае sendall() он просто отправляет буфер целевой (серверу), не имея информации о том, действительно ли этот буфер получен сервером или нет.

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

надеюсь, что это поможет!