Python的select模块中的select()函数如何正常工作?

 peanapple007 发布于 2023-02-12 03:19

我正在用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()功能的工作或指向良好的文档,那将是非常有用的.

谢谢.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有