#python-3.x #sockets
Вопрос:
Некоторые источники говорят, что recv должен иметь максимально возможную длину сообщения, например recv(1024):
message0 = str(client.recv(1024).decode('utf-8'))
Но другие источники говорят, что в нем должно быть общее количество байтов принимающего сообщения. Если сообщение «привет»:
message0 = str(client.recv(5).decode('utf-8'))
Как правильно использовать recv()?
Ответ №1:
Некоторые источники утверждают … Но другие источники говорят … сообщение …
Оба источника ошибочны.
Аргумент для recv
этого-максимальное количество байтов, которые нужно прочитать одновременно.
С сокетом UDP это размер сообщения, которое нужно прочитать или больше, но recv
в любом случае одно сообщение будет возвращено только одно. Если заданный размер меньше, чем сообщение, оно будет удалено, а остальное будет удалено.
С сокетом TCP (случай, о котором вы спрашиваете) в первую очередь нет понятия сообщения, поскольку TCP-это только поток байтов. recv
просто вернет количество байтов, доступных для чтения, до заданного размера. В частности, один recv
в получателе TCP не обязательно должен совпадать с одним send
в отправителе. Это может совпадать, и часто будет совпадать, если объем данных невелик, но нет никакой гарантии, и никогда не следует полагаться на это.
… message0 = str(клиент.recv(5).декодирование(‘utf-8’))
Обратите внимание, что decode('utf-8')
прямой вызов возвращаемых данных recv
-плохая идея. Сначала нужно убедиться, что все ожидаемые данные считаны, и только потом звонить decode('utf-8')
. Если считывается только часть данных, конец считываемых данных может находиться в середине символа, так как один символ в UTF-8 может быть закодирован в нескольких байтах (все, кроме символов ASCII). Если decode('utf-8')
вызывается с неполным закодированным символом, это вызовет исключение, и ваш код сломается.
Комментарии:
1. Теперь я в замешательстве, как работает recv, потому что обе мои интерпретации были неправильными. Спасибо, я поищу больше о recv и о том, как он работает с TCP, потому что ваш ответ (в хорошем смысле) был для меня продвинут.
2. @g_odim_3: Предположение, что TCP имеет семантику сообщения, и вывод из этого, что a
recv
в получателе совпадает с asend
в отправителе, к сожалению, является очень распространенной ошибкой. Трагедия в том. что часто кажется, что это работает, а затем, казалось бы, рабочий код отправляется. Который затем неожиданно и случайным образом выходит из строя для некоторых клиентов (нехватка памяти, нестабильность сети, разный MTU из-за использования VPN…), и никто не знает, почему.3. Это произошло в моем коде. Где вы узнали о розетках? Это могло бы помочь мне освоить основы этих функций и сокетов в целом.
4. @g_odim_3: «Где вы узнали о сокетах?» — ничего особенного. Просто многолетний опыт.