You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写无需等待输入的IRC聊天客户端?

重构方案:用select同时监听Socket和用户输入

你的问题核心是input()会阻塞整个循环,导致无法持续接收IRC消息。可以用Python的select模块同时监听Socket连接和标准输入(用户键盘输入),这样两者不会互相阻塞,实现一边接收消息一边等待用户输入的效果。

重构后的代码示例

import sys
import select

# 假设你的socket s已经设置为非阻塞并完成连接
while True:
    # 监听socket和标准输入,设置0.1秒超时避免占用过多CPU
    ready_to_read, _, _ = select.select([s, sys.stdin], [], [], 0.1)
    
    for fd in ready_to_read:
        if fd == s:
            # 处理IRC消息接收逻辑
            try:
                resp = s.recv(1024)
            except BlockingIOError:
                continue
            if not resp:
                # 连接断开时退出程序
                print("Connection closed by server")
                s.close()
                sys.exit(0)
            text = resp.decode('utf-8')
            # 换行打印消息,避免覆盖用户正在输入的内容
            print(f"\nINCOMING MESSAGE RECEIVED:\n{text}", end="")
            # 重新打印输入提示符,让用户继续输入
            print("> ", end="", flush=True)
            # 自动回复PING保持连接
            if text.startswith('PING'):
                msg = 'PONG ' + text.split()[1]
                s.send(bytes(msg, 'utf-8'))
        elif fd == sys.stdin:
            # 处理用户输入逻辑
            message = sys.stdin.readline()
            if not message:
                # 用户按Ctrl+D时退出程序
                s.close()
                sys.exit(0)
            # 去掉输入末尾的换行符,避免发送多余格式
            message = message.rstrip('\n')
            if message:
                s.send(bytes(message, 'utf-8'))
            # 重新打印输入提示符
            print("> ", end="", flush=True)

关键说明

  • select.select()会同时监听Socket和标准输入,一旦其中一方有数据就绪(Socket收到消息或用户输入内容),就会返回对应的文件描述符列表,不会阻塞整个循环。
  • 处理Socket消息时先换行再打印,避免覆盖用户正在输入的内容,之后重新打印提示符>,保证输入体验的连贯性。
  • 用sys.stdin.readline()替代input(),配合select实现非阻塞式的用户输入读取。
  • 添加了连接断开的判断逻辑,避免Socket关闭后程序持续报错。

内容的提问来源于stack exchange,提问作者Frank Harris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 13:24:55