Python的select模块中的select()函数如何工作? [英] How does the select() function in the select module of Python exactly work?

查看:133
本文介绍了Python的select模块中的select()函数如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Python编写面向网络的应用程序.我之前从事过使用阻塞套接字的工作,但是在对需求和概念有了更好的了解之后,我想使用非阻塞套接字(因此是事件驱动的服务器)编写应用程序.

I am working on writing a network-oriented application in Python. I had earlier worked on using blocking sockets, but after a better understanding of the requirement and concepts, I am wanting to write the application using non-blocking sockets and thus an event-driven server.

我知道Python中的select模块中的函数将用于方便地查看哪个套接字使我们感兴趣,等等.为此,我基本上是试图翻阅事件驱动服务器的几个示例,而我遇到了这个示例:

I understand that the functions in the select module in Python are to be used to conveniently see which socket interests us and so forth. Towards that I was basically trying to flip through a couple of examples of an event-driven server and I had come across this one:

"""
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() 

我似乎不了解的部分如下:

The parts that I didn't seem to understand are the following:

在代码段inputready,outputready,exceptready = select.select(input,[],[])中,我相信select()函数将为输入,输出和特殊情况返回三个可能为空的等待对象列表.因此,select()函数的第一个参数是包含服务器套接字和stdin的列表是有道理的.但是,我遇到困惑的地方是代码的else块.

In the code snippet inputready,outputready,exceptready = select.select(input,[],[]), I believe the select() function returns three possibly empty lists of waitable objects for input, output and exceptional conditions. So it makes sense that the first argument to the select() function is the list containing the server socket and the stdin. However, where I face confusion is in the else block of the code.

由于我们要遍历输入准备好使用的套接字列表,因此很明显,select()函数将选择准备读取的客户端套接字.但是,在使用recv()读取数据并发现套接字实际上已经发送了数据之后,我们希望将其回显给客户端.我的问题是,如何在不将其添加到作为第二个参数传递给select()函数调用的列表的情况下写入该套接字?意思是,如何在不使用select()作为可写套接字注册"的情况下直接在新套接字上调用send()?

Since we are for-looping over the list of inputready sockets, it is clear that the select() function will choose a client socket that is ready to be read. However, after we read data using recv() and find that the socket has actually sent data, we would want to echo it back to the client. My question is how can we write to this socket without adding it to the list passed as second argument to the select() function call? Meaning, how can we call send() on the new socket directly without 'registering' it with select() as a writable socket?

此外,为什么我们只在准备读取的套接字上循环(在这种情况下为inputready)?是否有必要甚至遍历outputready列表以查看准备好写入哪些套接字? 显然,我在这里错过了一些东西.

Also, why do we loop only over the sockets ready to be read (inputready in this case)? Isn't it necessary to loop over even the outputready list to see which sockets are ready to be written? Obviously, I am missing something here.

如果有人可以更详细地说明select()函数的工作原理或指向好的文档,这也将非常有帮助.

It would also be really helpful if somebody could explain in a little more detailed fashion the working of select() function or point to good documentation.

谢谢.

推荐答案

可能的代码段只是一个简单的示例,因此并不详尽.您可以自由地在每个套接字中进行读写,如果select不能告诉您它们已经准备好了.但是,当然,如果执行此操作,则不能确保send()不会阻塞. 因此,是的,最佳选择是还要依赖select进行编写操作. 还有许多其他功能具有相似的用途,在许多情况下,它们要比选择更好(例如, epoll ),但并非在所有平台上都可用. 有关select,epoll&的信息其他功能可以在Linux手册页中找到.

Probably that snippet of code is just a simple example and so it is not exhaustive. You are free to write and read in every socket, also if select does not tell you that they are ready. But, of course, if you do this you cannot be sure that your send() won't block. So, yes, it would be best practice to rely on select also for writing operations. There are also many other function which have a similar purpose and in many cases they are better then select (e.g. epoll), but they are not available on all platforms. Information about the select, epoll & other functions may be found in Linux man pages.

但是在python中,有很多不错的库用于处理许多连接,其中一些是: Twisted gevent

However in python there are many nice libraries used to handle many connections, some of these are: Twisted and gevent

这篇关于Python的select模块中的select()函数如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆