Python 下 sock.recv 产生阻塞的解决办法

2015-06-16 18:32:43 +08:00
 sbmzhcn
buf = 8192
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('192.168.1.10', 2000))
sock.sendall(data)
data = sock.recv(buf)
sock.close()

上面是最简单的socket连接程序,网上很多例子也是这样,但是recv这个地方如果服务器突然不响应了会产生阻塞,避免的办法网上大概有以下几个:
1. socket.settimeout() ,这个无法避免阻塞的,行不通
2. socket.setblocking(0) 这个必须再加个time.sleep(5)模拟阻塞,此方法兼容性很不友好。

想请问大家有什么特别好的方法没?比如异步的写法,给个示例也行。

5520 次点击
所在节点    Python
11 条回复
est
2015-06-16 18:39:09 +08:00
tornado, gevent, asyncio
binux
2015-06-16 18:42:39 +08:00
select
fangjinmin
2015-06-16 18:46:42 +08:00
用epoll
lilydjwg
2015-06-16 19:12:20 +08:00
@binux @fangjinmin 这两个都无法解决 recv(2) 阻塞的问题——除非把套接字设置成非阻塞。

不知道你的「无法避免阻塞」是什么意思。settimeout 会在你指定的时间之后返回的,并不会一直阻塞下去啊。你一刻也不想阻塞?可 setblocking(False) 之后,你为什么还要 sleep 呢,按之前的逻辑,这样不就「阻塞」了吗?——所以,你的需求到底是什么?
lilydjwg
2015-06-16 19:12:48 +08:00
binux
2015-06-16 19:15:42 +08:00
@lilydjwg 套接字 read ready 的泗洪 recv 也会阻塞吗?
hualuogeng
2015-06-16 19:19:06 +08:00
@lilydjwg 多好的XY
nirocfz
2015-06-16 20:28:12 +08:00
@binux 有可能,linux 的 man select 有这么一段话

Under Linux, select() may report a socket file descriptor as "ready for
reading", while nevertheless a subsequent read blocks. This could for
example happen when data has arrived but upon examination has wrong
checksum and is discarded. There may be other circumstances in which a
file descriptor is spuriously reported as ready. Thus it may be safer
to use O_NONBLOCK on sockets that should not block.
way2exluren
2015-06-16 20:53:40 +08:00
python 的socket在设置timeout后。
sock.timeout(5)
socket就变成非阻塞socket了……
楼主注意
zeayes
2015-06-17 09:00:52 +08:00
setblocking或者settimeout,然后catch住特定的异常处理掉,就好了。
feisan
2015-06-17 10:33:17 +08:00
@way2exluren

设置timeout会使socket变非阻塞?
sock.settimeout(0)才相当于sock.setblocking(0)吧?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/199052

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX