Разница между socket.send и socket.sendall () - PullRequest
0 голосов
/ 30 марта 2020

Я написал две программы для проверки этого p23_server.py для серверной части и p23_client.py для клиентской:

p23_server.py

#p23_server.py
import socket

HOST = '10.0.2.15'
PORT = 12345

server = socket.socket()
server.bind((HOST,PORT))
server.listen(1)
(client,addr) = server.accept()
while True:
    data = client.recv(32)
    if not data:
        break
    print(data.decode('utf-8'))
server.close()

p23_client.py

#p23_client.py
import socket
import sys

HOST = '10.0.2.15'
PORT = 12345

string = sys.argv[1]
data_to_send = string.encode('utf-8')


s = socket.socket()
s.connect((HOST,PORT))
#s.sendall(data_to_send)
s.send(data_to_send)
s.close()

Я запустил p23_server.py и затем выполнил команду:

wahalez@wahalez: ~ / dev / python $ python p23_client.py $ (python - c 'для i в диапазоне (1024): print ("a", end = "")')

для запуска на стороне клиента и посмотрите, что выводит сервер.

Я выполнил его один раз с помощью socket.send () и один раз с функцией socket.sendall (). Результаты одинаковы. Вопрос почему? не следует отправлять, просто отправьте данные один раз, а сервер получит 32 байта и все?

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

Почему обе функции дают одинаковый результат?

Ответы [ 3 ]

2 голосов
/ 30 марта 2020

только потому, что 99% времени send () удастся отправить все данные за 1 go. Теоретически, когда вы используете send (), вы можете не увидеть все данные на сервере.

Чтобы подчеркнуть разницу, пример псевдо-реализации sendall:

def sendall(data):
    already_sent = 0
    while already_sent < len(data):
        already_sent += send(data[already_sent:])
2 голосов
/ 30 марта 2020

Документация понятна:

socket.send (bytes [, flags])
Отправка данных в сокет. Сокет должен быть подключен к удаленному разъему. Необязательный аргумент flags имеет то же значение, что и для recv () выше. Возвращает количество отправленных байтов. Приложения отвечают за проверку того, что все данные были отправлены; если были переданы только некоторые данные, приложение должно попытаться доставить оставшиеся данные. Для получения дополнительной информации по этой теме c обратитесь к HOWTO по программированию сокетов.

Изменено в версии 3.5: если системный вызов прерывается и обработчик сигнала не вызывает исключение, метод теперь повторяет системный вызов вместо того, чтобы вызывать исключение InterruptedError (объяснение см. в PEP 475).

socket.sendall (bytes [, flags])
Отправка данных в сокет. Сокет должен быть подключен к удаленному разъему. Необязательный аргумент flags имеет то же значение, что и для recv () выше. В отличие от send (), этот метод продолжает отправлять данные из байтов до тех пор, пока все данные не будут отправлены или не произойдет ошибка. Ни один не возвращается в случае успеха. При ошибке возникает исключение, и невозможно определить, сколько данных, если таковые имеются, были успешно отправлены.

TL; DR send возвращает количество отправленных байтов, которое может быть меньше запрашиваемой суммы. sendall возвращает None при успешной передаче всех данных и вызывает исключение при ошибке.

0 голосов
/ 30 марта 2020

Почему обе функции дают одинаковый результат?

Поскольку вы отправляете так мало данных, они либо всегда будут работать полностью, либо полностью сбоят.

То, что делает sendall, это просто l oop и send полезная нагрузка пока все не будет отправлено. Если все вписывается в первый send, то нет никакой разницы.

...