我正在用Python编写面向网络的应用程序.我之前曾使用过阻塞套接字,但在更好地理解了需求和概念后,我想使用非阻塞套接字编写应用程序,从而编写一个事件驱动的服务器.
据我所知,Python中select模块中的函数用于方便地查看哪个socket对我们感兴趣等等.为此,我基本上试图翻阅事件驱动服务器的几个例子,我遇到过这个:
""" An echo server that uses select to handle multiple clients at a time. Entering any line of input at the terminal will exit the server. """ import select import socket import sys host = '' port = 50000 backlog = 5 size = 1024 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((host,port)) server.listen(backlog) input = [server,sys.stdin] running = 1 while running: inputready,outputready,exceptready = select.select(input,[],[]) for s in inputready: if s == server: # handle the server socket client, address = server.accept() input.append(client) elif s == sys.stdin: # handle standard input junk = sys.stdin.readline() running = 0 else: # handle all other sockets data = s.recv(size) if data: s.send(data) else: s.close() input.remove(s) server.close()
我似乎不理解的部分如下:
在代码片段中inputready,outputready,exceptready = select.select(input,[],[])
,我相信该select()
函数返回三个可能为输入,输出和异常条件的可等对象的空列表.因此,select()
函数的第一个参数是包含服务器套接字和stdin的列表是有道理的.但是,我遇到困惑的地方就是else
代码块.
由于我们用于循环输入套接字列表,很明显该select()
函数将选择一个可以读取的客户端套接字.但是,在我们使用recv()
并读取套接字实际已发送数据之后,我们希望将其回送给客户端.我的问题是我们如何写入这个套接字而不将其添加到作为select()
函数调用的第二个参数传递的列表中?意思是,我们如何send()
直接调用新套接字而不将其"注册" select()
为可写套接字?
另外,为什么我们只在准备好读取的套接字上循环(在这种情况下是inputready)?是否有必要循环甚至输出已完成列表以查看哪些套接字已准备好写入?显然,我在这里遗漏了一些东西.
如果有人能够以更详细的方式解释select()
功能的工作或指向良好的文档,那将是非常有用的.
谢谢.