Python套接字聊天客户端 - select.select()和sys.stdin的问题
我现在正在尝试制作一个小型的聊天客户端,包括一个服务器和一些客户端。我在网上找到了一些代码,想用它作为我自己项目的基础。现在我遇到的问题是,这段代码是用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这样的异步框架可能已经解决了这个问题。