python 中 select 函数求解

2015-10-07 17:14:30 +08:00
 yang2yang
使用 select 的服务器

```python
import select
import socket
import Queue

#create a socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.setblocking(False)
#set option reused
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR , 1)

server_address= ('localhost',10001)
server.bind(server_address)

server.listen(10)

#sockets from which we except to read
inputs = [server]

#sockets from which we expect to write
outputs = []

#Outgoing message queues (socket:Queue)
message_queues = {}

#A optional parameter for select is TIMEOUT
timeout = 10

while inputs:
print "waiting for next event"
#--------------------------------------------------
readable , writable , exceptional = select.select(inputs, outputs, inputs)
#--------------------------------------------------
for temp in readable:
print temp
print "writable:",writable
print "exceptional",exceptional

# When timeout reached , select return three empty lists
if not (readable or writable or exceptional) :
print "Time out ! "
break;
for s in readable :
if s is server:
# A "readable" socket is ready to accept a connection
connection, client_address = s.accept()
print " connection from ", client_address
connection.setblocking(0)
inputs.append(connection)
message_queues[connection] = Queue.Queue()
...........................略
```


创建十个 socket 用于连接服务器


```python
import socket

messages = ["This is the message" ,
"It will be sent" ,
"in parts "]

print "Connect to the server"

server_address = ("localhost",10001)

#Create a TCP/IP sock

socks = []

for i in range(10):
socks.append(socket.socket(socket.AF_INET,socket.SOCK_STREAM))

for s in socks:
s.connect(server_address)

counter = 0
for message in messages :
#Sending message from different sockets
for s in socks:
counter+=1
print " %s sending %s" % (s.getpeername(),message+" version "+str(counter))
s.send(message+" version "+str(counter))
#Read responses on both sockets
for s in socks:
data = s.recv(1024)
print " %s received %s" % (s.getpeername(),data)
if not data:
print "closing socket ",s.getpeername()
s.close()
```

问题:
( 1 )服务器例子中的 select 函数是在一个怎么样的条件下才会返回?
( 2 )是不是只要有一个 socket 进行连接就会进行返回?还是说等到十个 socket 都连接了才返回?
( 3 )可以的话,讲讲 select 函数具体的运作过程?求解惑, thx
2805 次点击
所在节点    Python
5 条回复
RTNelo
2015-10-07 18:39:23 +08:00
yang2yang
2015-10-07 19:24:54 +08:00
好的,其实我也是看过类似的文档。但是,可能我没看到,或者说不能完全理解(毕竟 English 不是很好 。。。。)刚才也是读了这个文档,在这个官方文档中还是没有提到 select 函数在 timeout 不填的时候返回时,是等到全部的 socket 连接入,还是只要有一个 socket 连入就返回。下面这两句应该是指 timeout 有值和 timeout 为 0 时的情况??还是说为 0 的情况和不填的情况是一样的?
When the timeout argument is omitted the function blocks until at least one file descriptor is ready.A time-out value of zero specifies a poll and never blocks.
mckelvin
2015-10-07 21:57:12 +08:00
@yang2yang 上面的英语描述已经解答了你的疑惑了啊!

> 下面这两句应该是指 timeout 有值和 timeout 为 0 时的情况??还是说为 0 的情况和不填的情况是一样的?

- 不指定 timeout 的情况下,只要有 >= 1 个文件描述符响应了就立即返回,否则一直阻塞着。
- timeout = 0 的情况下,永远不阻塞(立即返回)
- timeout > 0 的情况下,有 >= 1 个文件描述符响应了就立即返回,如果过了 timeout 时间一个文件描述符都没响应的话,那就不等待了,立即返回。

建议阅读:

- http://www.ulduzsoft.com/2014/01/select-poll-epoll-practical-difference-for-system-architects/#comment-39719
yang2yang
2015-10-07 23:20:59 +08:00
谢谢回复的各位,明白了
ryd994
2015-10-07 23:39:37 +08:00
要是必须全部响应才返回的话,还要 select 干嘛?直接一个个 blocking 地读过去不就完了吗

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

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

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

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

© 2021 V2EX