К вашему сведению, если вы решите использовать тайм-ауты ... вам нужно знать, как обрабатывать тайм-аут. в этом вопросе SO говорится об обработке, когда происходит тайм-аут: stackoverflow.com/questions/16745409
Trevor Boyd Smith
Ответы:
126
Типичный подход - использовать select (), чтобы дождаться, пока данные станут доступны или пока не истечет время ожидания. Звоните только recv()тогда, когда данные действительно доступны. На всякий случай мы также установили сокет в неблокирующий режим, чтобы гарантировать, что recv()он никогда не будет блокироваться бесконечно. select()также может использоваться для ожидания более чем одного сокета одновременно.
Если у вас много дескрипторов открытых файлов, poll () является более эффективной альтернативой select().
Другой вариант - установить тайм-аут для всех операций с использованием сокета socket.settimeout(), но я вижу, что вы явно отклонили это решение в другом ответе.
Использование select- это хорошо, но та часть, где вы говорите «вы не можете», вводит в заблуждение, поскольку есть socket.settimeout().
носкло
1
Сейчас лучше, но я не вижу, где ответ был «явно отклонен».
nosklo
7
Одно предостережение при использовании select- если вы работаете на машине с Windows, selectполагается на библиотеку WinSock, которая имеет привычку возвращаться, как только будут получены некоторые данные, но не обязательно все . Таким образом, вам нужно включить цикл, чтобы продолжать звонить, select.select()пока не будут получены все данные. Как вы узнаете, что получили все данные (к сожалению), решать вам - это может означать поиск строки терминатора, определенное количество байтов или просто ожидание определенного тайм-аута.
JDM
4
Почему необходимо установить сокет без блокировки? Я не думаю, что это имеет значение для вызова select (и он блокируется до тех пор, пока дескриптор не может быть прочитан или пока не истечет время ожидания в этом случае), и recv () не будет блокироваться, если выбор будет удовлетворен. Я пробовал использовать recvfrom (), и, похоже, он работает правильно без setblocking (0).
HankB
1
Было ready[0]бы неверно, только если бы в ответе сервера нет тела?
Это не время ожидания recv (по крайней мере, когда я это пробовал). Истекло время ожидания только для accept ().
Oren S
9
Кажется, что socket.recv () истекает для меня нормально после установки socket.settimeout (), точно так, как задумано. Я это выдумываю? Кто-нибудь еще может это подтвердить?
Aeonaut
3
@Aeonaut Я думаю, что в большинстве случаев у recv () истекает время ожидания, но есть состояние гонки. В socket.recv () Python (2.6) вызывает внутри себя select / poll с тайм-аутом, а затем сразу после этого вызывается recv (). Поэтому, если вы используете блокирующий сокет и между этими двумя вызовами происходит сбой другой конечной точки, вы можете бесконечно зависать на recv (). Если вы используете неблокирующий сокет, python не вызывает select.select внутри, поэтому я думаю, что ответ Даниэля Штутцбаха правильный.
emil.p.stanchev 04
4
На самом деле, я, вероятно, неправильно понял, когда возвращается select (), поэтому, пожалуйста, сотрите предыдущий комментарий. В руководстве Beej говорится, что приведенное выше является допустимым способом реализации тайм-аута для recv: beej.us/guide/bgnet/output/html/singlepage/… так что я доверяю этому источнику.
emil.p.stanchev 04
2
Я не уверен, почему решение, которое использует, selectявляется предпочтительным, когда это решение является однострочным (проще в обслуживании, меньше рисков при неправильной реализации) и использует select под капотом (реализация такая же, как и ответ @DanielStuzbach).
Я думаю, что он попадает в то же самое, что и я, где неважно как тыкаешь и толкаешь эту функцию, она зависает. Я пробовал 2 или 4 таймаута, но он все еще зависает. settimeout тоже зависает.
Casey Daniel
1
Когда вы вызываете .settimeout()более одного раза, вы можете setdefaulttimeout()в первую очередь вызвать метод.
mvarge
12
Вы можете установить тайм-аут до получения ответа, а после получения ответа вернуть значение None:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5.0)
data = sock.recv(1024)
sock.settimeout(None)
Тайм-аут, который вы ищете, - это тайм-аут сокета подключения, а не основного сокета, если вы реализуете серверную часть. Другими словами, существует еще один тайм-аут для объекта сокета подключения, который является выходом socket.accept()метода. Следовательно:
sock.listen(1)
connection, client_address = sock.accept()
connection.settimeout(5)# This is the one that affects recv() method.
connection.gettimeout()# This should result 5
sock.gettimeout()# This outputs None when not set previously, if I remember correctly.
Если вы реализуете клиентскую сторону, это будет просто.
Как упоминалось в предыдущих ответах, вы можете использовать что-то вроде: .settimeout()
Например:
import socket
s = socket.socket()
s.settimeout(1)# Sets the socket to timeout after 1 second of no activity
host, port ="somehost",4444
s.connect((host, port))
s.send("Hello World!\r\n")try:
rec = s.recv(100)# try to receive 100 bytesexcept socket.timeout:# fail after 1 second of no activityprint("Didn't receive data! [Timeout]")finally:
s.close()
Вы можете использовать socket.settimeout()which принимает целочисленный аргумент, представляющий количество секунд. Например, socket.settimeout(1)установит тайм-аут на 1 секунду.
Он предоставляет буферизованный сокет, который предоставляет множество очень полезных функций, таких как:
.recv_until()#recv until occurrence of bytes.recv_closed()#recv until close.peek()#peek at buffer but don't pop values.settimeout()#configure timeout (including recv timeout)
Ответы:
Типичный подход - использовать select (), чтобы дождаться, пока данные станут доступны или пока не истечет время ожидания. Звоните только
recv()
тогда, когда данные действительно доступны. На всякий случай мы также установили сокет в неблокирующий режим, чтобы гарантировать, чтоrecv()
он никогда не будет блокироваться бесконечно.select()
также может использоваться для ожидания более чем одного сокета одновременно.Если у вас много дескрипторов открытых файлов, poll () является более эффективной альтернативой
select()
.Другой вариант - установить тайм-аут для всех операций с использованием сокета
socket.settimeout()
, но я вижу, что вы явно отклонили это решение в другом ответе.источник
select
- это хорошо, но та часть, где вы говорите «вы не можете», вводит в заблуждение, поскольку естьsocket.settimeout()
.select
- если вы работаете на машине с Windows,select
полагается на библиотеку WinSock, которая имеет привычку возвращаться, как только будут получены некоторые данные, но не обязательно все . Таким образом, вам нужно включить цикл, чтобы продолжать звонить,select.select()
пока не будут получены все данные. Как вы узнаете, что получили все данные (к сожалению), решать вам - это может означать поиск строки терминатора, определенное количество байтов или просто ожидание определенного тайм-аута.ready[0]
бы неверно, только если бы в ответе сервера нет тела?есть
socket.settimeout()
источник
select
является предпочтительным, когда это решение является однострочным (проще в обслуживании, меньше рисков при неправильной реализации) и использует select под капотом (реализация такая же, как и ответ @DanielStuzbach).Как уже упоминалось,
select.select()
иsocket.settimeout()
будут работать.Обратите внимание, что вам может потребоваться
settimeout
дважды позвонить для ваших нужд, напримеристочник
.settimeout()
более одного раза, вы можетеsetdefaulttimeout()
в первую очередь вызвать метод.Вы можете установить тайм-аут до получения ответа, а после получения ответа вернуть значение None:
источник
Тайм-аут, который вы ищете, - это тайм-аут сокета подключения, а не основного сокета, если вы реализуете серверную часть. Другими словами, существует еще один тайм-аут для объекта сокета подключения, который является выходом
socket.accept()
метода. Следовательно:Если вы реализуете клиентскую сторону, это будет просто.
источник
Как упоминалось в предыдущих ответах, вы можете использовать что-то вроде:
.settimeout()
Например:Надеюсь, это поможет!!
источник
Вы можете использовать
socket.settimeout()
which принимает целочисленный аргумент, представляющий количество секунд. Например,socket.settimeout(1)
установит тайм-аут на 1 секунду.источник
попробуйте это, он использует базовый C.
источник
SO_RCVTIMEO
иSO_SNDTIMEO
.2
и почему100
? Какое значение тайм-аута? В каком агрегате?timeval = struct.pack('ll', sec, usec)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)
usec = 10000 означает 10 мсисточник
Кричать, чтобы: https://boltons.readthedocs.io/en/latest/socketutils.html
Он предоставляет буферизованный сокет, который предоставляет множество очень полезных функций, таких как:
источник