如何正确使用 python socket.settimeout()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34371096/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use python socket.settimeout() properly
提问by Jorky10
As far as I know, when you call socket.settimeout(value)
and you set a float value greater than 0.0, that socket will raise a scocket.timeout when a call to, for example, socket.recv
has to wait longer than the value specified.
据我所知,当您调用socket.settimeout(value)
并设置大于 0.0 的浮点值时,该套接字将引发 scocket.timeout 例如,当调用socket.recv
必须等待比指定值更长的时间时。
But imagine I have to receive a big amount of data, and I have to call recv()
several times, then how does settimeout affect that?
但是想象一下,我必须接收大量数据,并且必须recv()
多次调用,那么 settimeout 对此有何影响?
Given the following code:
鉴于以下代码:
to_receive = # an integer representing the bytes we want to receive
socket = # a connected socket
socket.settimeout(20)
received = 0
received_data = b""
while received < to_receive:
tmp = socket.recv(4096)
if len(tmp) == 0:
raise Exception()
received += len(tmp)
received_data += tmp
socket.settimeout(None)
The third line of the code sets the timeout of the socket to 20 seconds. Does that timeout reset every iteration? Will timeout be raised only if one of those iteration takes more than 20 seconds?
代码的第三行将套接字的超时设置为 20 秒。每次迭代都会重置超时吗?只有当其中一个迭代超过 20 秒时才会引发超时吗?
A) How can I recode it so that it raises an exception if it is taking more than 20 seconds to receive all the expected data?
A) 如果接收所有预期数据的时间超过 20 秒,我该如何对其进行重新编码,以便引发异常?
B) If I don't set the timeout to None after we read all data, could anything bad happen? (the connection is keep-alive and more data could be requested in the future).
B) 如果我在读取所有数据后没有将超时设置为 None,会发生什么不好的事情吗?(连接保持活动状态,将来可能会请求更多数据)。
采纳答案by Lav
Timeout applies to a single call to socket read/write operation. So next call it will be 20 seconds again.
超时适用于对套接字读/写操作的单个调用。所以下一次调用将再次是 20 秒。
A) To have a timeout shared by several consequential calls, you'll have to track it manually. Something along these lines:
A) 要让多个后续调用共享超时,您必须手动跟踪它。沿着这些路线的东西:
deadline = time.time() + 20.0
while not data_received:
if time.time() >= deadline:
raise Exception() # ...
socket.settimeout(deadline - time.time())
socket.read() # ...
B) Any code that's using a socket with a timeout and isn't ready to handle socket.timeout
exception will likely fail. It is more reliable to remember the socket's timeout value before you start your operation, and restore it when you are done:
B) 任何使用带有超时的套接字且未准备好处理socket.timeout
异常的代码都可能会失败。在开始操作之前记住套接字的超时值更可靠,并在完成后恢复它:
def my_socket_function(socket, ...):
# some initialization and stuff
old_timeout = socket.gettimeout() # Save
# do your stuff with socket
socket.settimeout(old_timeout) # Restore
# etc
This way, your function will not affect the functioning of the code that's calling it, no matter what either of them do with the socket's timeout.
这样,您的函数不会影响调用它的代码的功能,无论它们中的任何一个如何处理套接字超时。
回答by barny
The timeout applies to each call to recv().
超时适用于对 recv() 的每次调用。
A) simply use your existing timeout and call recv(to_receive) - I.e. Try to receive all the data in one recv call - in fact I don't see why you shouldn't use this as the default way it works
A) 只需使用您现有的超时并调用 recv(to_receive) - 即尝试在一个 recv 调用中接收所有数据 - 事实上我不明白为什么你不应该使用它作为它的默认工作方式
B) No nothing bad could happen, but any other code which uses that socket needs to be aware of handling timeout.
B) 不会有什么不好的事情发生,但是使用该套接字的任何其他代码都需要注意处理超时。
On your existing code, shouldn't the recv() call be recv(max(4096,to_receive-received)) - that way you won't unintentionally consume any data which follows after the to_receive bytes.
在您现有的代码中, recv() 调用不应该是 recv(max(4096,to_receive-received)) - 这样您就不会无意中消耗 to_receive 字节之后的任何数据。
回答by Himanshu Kanojiya
See my server script, you will get the idea to use it properly.
请参阅我的服务器脚本,您将了解正确使用它的想法。
import socket
import sys
fragments = []
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("192.168.1.4",9001))
s.listen(5)
while True:
c,a = s.accept()
c.settimeout(10.0)
print "Someone came in Server from %s and port %s" %(a[0],a[1])
c.send("Welcome to system")
while True:
chunk = c.recv(2048)
if not chunk.strip():
break
else:
fragments.append(chunk)
continue
combiner = "".join(fragments)
print combiner
shutdown = str(raw_input("Wanna Quit(Y/y) or (N/n): "))
if shutdown == 'Y' or shutdown == 'y':
c.close()
sys.exit()
else:
continue
This script is just to give you an idea about the socket.settimeout().
这个脚本只是让你了解 socket.settimeout()。