Python - 使用选择器的非阻塞套接字

2024-03-04

我的问题简而言之: 我不知道选择器如何知道哪个套接字应该首先读取或写入。

它是一个可以处理多连接的服务器,其流程应该是:

  1. 服务器创建监听套接字
  2. 客户端创建2个套接字并将它们连接到服务器
  3. 客户端2套接字发送消息
  4. 服务器 2 套接字回显这些消息,客户端和服务器关闭 联系

这就是发生的情况,但是如果创建的服务器套接字首先写入,则连接将立即关闭或抛出异常(?),因为它甚至不调用 send 并且客户端套接字不会接收任何内容。那么选择器如何知道哪些套接字应该首先准备好写入/读取呢?为了理解这一点我错过了哪些信息?

Server:

import socket
import selectors
import types

host = "127.0.0.1"
port = 63210

def accept_wrapper(sock):
    conn, addr = sock.accept()
    print('accepted connection from', addr)
    conn.setblocking(False)
    data = types.SimpleNamespace(addr=addr, inb=b'', outb=b'')
    events = selectors.EVENT_READ | selectors.EVENT_WRITE
    sel.register(conn, events, data=data)

def service_connection(key, mask):
    sock = key.fileobj
    data = key.data
    if mask & selectors.EVENT_READ:
        recv_data = sock.recv(1024)
        if recv_data:
            data.outb += recv_data
        else:
            print('closing connection to', data.addr)
            sel.unregister(sock)
            sock.close()
    if mask & selectors.EVENT_WRITE:
        if data.outb:
            print('echoing', repr(data.outb), 'to', data.addr)
            sent = sock.send(data.outb)
            data.outb = data.outb[sent:]

sel = selectors.DefaultSelector()

lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.bind((host, port))
lsock.listen()
print('listening on', (host, port))
lsock.setblocking(False)
sel.register(lsock, selectors.EVENT_READ, data=None)

while True:
    events = sel.select(timeout=None)
    for key, mask in events:
        if key.data is None:
            accept_wrapper(key.fileobj)
        else:
            service_connection(key, mask)

Client:

import socket
import selectors
import types

host = "127.0.0.1"
port = 63210
num_conns = 2
messages = [b'Message 1 from client.', b'Message 2 from client.']

def start_connections(host, port, num_conns):
    server_addr = (host, port)
    for i in range(0, num_conns):
        connid = i + 1
        print('starting connection', connid, 'to', server_addr)
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setblocking(False)
        sock.connect_ex(server_addr)
        events = selectors.EVENT_READ | selectors.EVENT_WRITE
        data = types.SimpleNamespace(connid=connid,
                                     msg_total=sum(len(m) for m in messages),
                                     recv_total=0,
                                     messages=list(messages),
                                     outb=b'')
        sel.register(sock, events, data=data)

def service_connection(key, mask):
    sock = key.fileobj
    data = key.data
    if mask & selectors.EVENT_READ:
        recv_data = sock.recv(1024)
        if recv_data:
            print('received', repr(recv_data), 'from connection', data.connid)
            data.recv_total += len(recv_data)
        if not recv_data or data.recv_total == data.msg_total:
            print('closing connection', data.connid)
            sel.unregister(sock)
            sock.close()
    if mask & selectors.EVENT_WRITE:
        if not data.outb and data.messages:
            data.outb = data.messages.pop(0)
        if data.outb:
            print('sending', repr(data.outb), 'to connection', data.connid)
            sent = sock.send(data.outb)
            data.outb = data.outb[sent:]

sel = selectors.DefaultSelector()
start_connections(host, port, num_conns)

while True:
    events = sel.select(timeout=None)
    for key, mask in events:
        service_connection(key, mask)

套接字实际上并不直接写入对等点,也不从对等点读取。相反,它们写入本地套接字特定的写入缓冲区并从套接字特定的读取缓冲区读取。操作系统内核关心将数据从套接字写入缓冲区传送到对等方,并将从对等方接收到的数据包放入套接字接收缓冲区。

可以使用以下函数监视这些内核套接字缓冲区的状态以及这些缓冲区的更改select, poll, kqueue。本质上:如果套接字写入缓冲区中有空间,则套接字被认为是可写的。如果套接字读取缓冲区中有数据,则认为套接字是可读的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python - 使用选择器的非阻塞套接字 的相关文章

随机推荐

  • R 中生存数据的左删失

    我想对左右删失的数据进行生存分析 Kaplan Meier 和 Cox PH 建模 我正在研究特定基因 基因 0 或 1 存在与不存在时发生心律失常 AF 的时间 然而 一些受试者在招募时被发现已经存在心律失常 因此应该进行审查 我已阅读生
  • Twisted 中的多重响应

    我正在尝试开发简单的TCP 使用 Twisted 和 Pygame 进行客户端 服务器游戏 但我在向客户端发送数据时遇到困难 Twisted 不允许我连续发送多个响应 这就是我想做的 我有方法处理玩家状态更改并将其重新发送给其他客户端 de
  • ASP.NET Core 中 Mongodb 数据存储的基于简单令牌的身份验证/授权

    我需要实现非常简单的身份验证机制 基本上有两个角色 Owners and Users 我认为拥有 Enum 就足够了 应用程序本身是SPA 通过Asp net core实现webapi 我看到文章 如何使用 EF Identity 实现它
  • 确定 MIDI 文件的时间划分

    我正在用Python编写一个脚本来解析MIDI文件 是的 我知道Python存在MIDI解析库 但对于我的用例来说 如果我从头开始制作它是最简单的 我遇到的问题之一是时间划分 标头的最后两个字节指定时间划分 但我无法确定文件的时间划分是否以
  • 正则表达式:匹配该字符串

    我无法弄清楚这一点 22 584 r n t t tl 6 579 22 我想匹配 r n t t t 并替换为一个空格 问题是数量 t r and n 波动 周围的人物也是如此 Help s s g s rnt g
  • 如何在 tkinter 中给定时间后运行函数?

    所以我在 tkinter 的画布上有一张 gif 图片 我想让这张照片变成另一张照片 但只持续三秒钟 并将其恢复到原始图片 def startTurn self newgif PhotoImage file 2h gif self left
  • UISlider 无法在原型单元中滑动

    我在故事板的视图控制器中设计了一个原型单元 但不幸的是UISlider细胞内不滑动 Note 此故事板启用了自动布局 Design 这是代码 渲染单元格UITableview UITableViewCell tableView UITabl
  • GitHub PR 使用什么 git 命令来显示差异

    我想使用命令行来生成 GitHub 提供的相同差异 帮助页面将其描述为 头部分支的尖端与头部上次与基础分支同步的提交之间的比较 https help github com articles about comparing branches
  • 拆分unity配置文件

    我需要将我的统一配置拆分为 n 个不同的文件 以便我可以将其中一些文件选择到同一个统一容器中 好的 已经太晚了 但我可以回答 你需要这样的东西 private IUnityContainer ReadContainer var unityC
  • 为什么这个函数没有定义?

    我希望我已经过去了 但为什么单击按钮时调整大小未定义 document ready function var w 320 480 var h 480 620 function resize input scale width w input
  • 如何正确模拟bean HikariDataSource?

    我使用 Mockito 编写了集成测试 但是当设置了与数据库的连接时它可以工作 实际上测试只是检查访问某些端点的可能性 与数据访问层无关 所以我还不需要数据库 数据库关闭时测试失败的原因 HikariDatasource 在 spring
  • 如何限制我的 Windows 应用程序生成进程的单个实例?

    I am working on a Windows application I have created a help file chm using a third party tool and I call it from the Win
  • 创建用于生成 Firebase CustomToken 的服务器时,我仅使用服务帐户还是以某种方式在幕后还使用用户凭据?

    我们很快就会将该项目投入生产 1 我们的移动应用程序将通过将其发布到我们的内部微服务器来创建汇款 此类 post 请求将返回从我们的内部 NodeJs 服务器生成的 CustomToken 2 我们的内部微服务会将此类传输复制到 Fires
  • 将时间值设置到数据框单元格中

    我正在尝试将时间值设置到数据框中 ps data frame t rep NA 2 ps 1 1 strptime 10 30 00 H M S 但我收到错误 provided 9 variables to replace 1 variab
  • 如何使用 grunt 将编译好的 jade 文件复制到目标文件夹

    对于我正在开发的单页应用程序 我具有以下结构 dist css js lib partials 索引 html src css js lib views partials 索引 jade 目录dist将由express服务器用来为项目提供服
  • 清除 Visual Studio 解决方案中的所有断点

    是否有快捷方式可以清除 Visual Studio 解决方案中所有项目内的所有断点 调试 gt 删除所有断点 or Shortcut CTRL SHIFT F9 这适用于调试模式以及
  • React Native:如何检测带有 Notch 的 iPhone?

    我正在尝试举一个具体的案例iPhone Xs Max in react native 这就是我的代码IphoneX from 反应本机 iphone x helper https www npmjs com package react na
  • 读取单选按钮值 - Angular 2

    我正在尝试读取单选按钮值 以角度 2 表示 索引 html
  • 忽略连接字符串中的连接超时属性

    我正在用 C 构建一个应用程序 我使用的连接字符串如下 DSN SomeDataSource Trusted Connection yes Uid SomeId pwd somePwd Connection Timeout x 但无论我设置
  • Python - 使用选择器的非阻塞套接字

    我的问题简而言之 我不知道选择器如何知道哪个套接字应该首先读取或写入 它是一个可以处理多连接的服务器 其流程应该是 服务器创建监听套接字 客户端创建2个套接字并将它们连接到服务器 客户端2套接字发送消息 服务器 2 套接字回显这些消息 客户