Python套接字聊天客户端 - select.select()和sys.stdin的问题

5 投票
2 回答
6123 浏览
提问于 2025-04-18 15:35

我现在正在尝试制作一个小型的聊天客户端,包括一个服务器和一些客户端。我在网上找到了一些代码,想用它作为我自己项目的基础。现在我遇到的问题是,这段代码是用Python 2.x写的,而我使用的是3.x。其实需要转换的地方不多,但我在程序使用sys.stdin时遇到了一些问题。

原始代码可以在这里找到。

这是我的代码:

import sys, socket, select

def chat_client():
    host = 'localhost'
    port = 9009

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(2)

    # connect to remote host
    try :
        s.connect((host, port))
    except :
        print('Unable to connect')
        sys.exit()

    print('Connected to remote host. You can start sending messages')
    sys.stdout.write('[Me] '); sys.stdout.flush()

    while 1:
        socket_list = [sys.stdin, s]

        read_sockets, write_sockets, error_sockets = select.select(socket_list , [], [])

        for sock in read_sockets:            
            if sock == s:
                # incoming message from remote server, s
                data = sock.recv(4096)
                if not data :
                    print('\nDisconnected from chat server')
                    sys.exit()
                else :
                    #print data
                    sys.stdout.write(data)
                    sys.stdout.write('[Me] '); sys.stdout.flush()     

            else :
                # user entered a message
                msg = sys.stdin.readline()
                s.send(msg)
                sys.stdout.write('[Me] '); sys.stdout.flush() 

if __name__ == "__main__":
    chat_client()

我遇到的错误是:

`[Me] Traceback (most recent call last):
  File "client.py", line 46, in <module>
    chat_client()
  File "client.py", line 25, in chat_client
    read_sockets, write_sockets, error_sockets = select.select(socket_list , [],
 [])
OSError: [WinError 10038] An operation was attempted on something that is not a
socket`

显然,我会出现这个错误是因为没有任何输入,但由于我找不到任何我能理解的文档来解释下面的代码行,所以我很难修复这个问题。我不知道通过sys.stdin应该接收什么样的输入。

`socket_list = [sys.stdin, s]
read_sockets, write_sockets, error_sockets = select.select(socket_list , [], [])`

如果我对我的问题没有解释清楚,请回复我,我会提供你需要的任何信息。谢谢你的帮助 :)

2 个回答

-1

把你的代码 read_sockets, write_sockets, error_sockets = select.select(socket_list , [], []) 替换成下面的内容:

  `read_sockets = select.select([s], [], [], 1)[0]
   import msvcrt
   if msvcrt.kbhit(): read_sockets.append(sys.stdin)`    
4

WinError提示你是在使用Windows系统。sys.stdin在类Unix系统上可以当作一个网络连接来用,但在Windows上就不行。

详细信息可以查看这里:https://docs.python.org/3/library/select.html

需要注意的是,在Windows上,这个功能只适用于网络连接;而在其他操作系统上,它还可以用于其他文件类型(特别是在Unix系统上,它可以用于管道)。

快速搜索一下可以发现,有人可能会通过在一个线程上对网络连接使用select,而在另一个线程上阻塞本地输入输出,来绕过这个问题,但我不能保证这是最好的或唯一的方法。像Twisted这样的异步框架可能已经解决了这个问题。

撰写回答