所以我正在搞乱一个非常简单的echo服务器/客户端的交易。我最终会制作一个游戏服务器,但是现在我只想设置基本部件。
这是服务器:http://pastebin.com/qtfrMGur
以下是客户:http://pastebin.com/3VK3VxPX
所以,我的问题是,当客户端断开连接时,我得到socket.error:[Errno 10054]远程主机强行关闭现有连接。当可读套接字列表没有待处理信息时,我认为select.select()返回false(或空列表,无论如何)。这似乎是错误的原因,但是如果客户端不再存在,为什么select.select()返回true(第26行)?当我尝试检索第27行中的某些信息时发生实际错误。我真的很困惑,假设套接字的客户端已关闭,不应该只返回[],然后转到其他地方第31行并销毁该客户?
我真的不知道还有什么要发布,这看起来像是一个非常基本的问题,通常我使用一个更加抽象的库,如扭曲,这使得它很容易,但对于这个项目,我必须使用传统的BSD套接字。如果你们有任何其他信息,你只需要问。
感谢。
编辑:所以我在那里放了一个print语句来打印select.select(...)[0]的值,如下所示:
for cl in clients:
ready = select.select([cl], [], [], .1)[0]
print ready
if ready:
data = cl.recv(size)
if data:
print data
#cl.send(data)
else:
print "Client Quit\n"
clients.remove(cl)
cl.shutdown(socket.SHUT_RDWR)
cl.close()
print len(clients)
正如您所看到的,我现在也正在关机。问题是,当客户端退出时,select.select(...)将客户端套接字作为可读源返回,因此cl.recv被调用,然后抛出错误,因为cl在另一端关闭。至少这是我的怀疑。
那么,有人可以解释一下我在这里做错了什么吗?为什么客户端发送最后一条死亡消息,是否应该利用某种功能?
由于
EDIT2:所以我们开启了我的debian机器并且代码完美运行,只有在Windows中才会这样做。这是某种错误吗?我的印象是套接字库抽象了引擎盖下的所有内容,使得操作系统之间的界面相同。
答案 0 :(得分:1)
在客户端关闭套接字之前,你应该调用套接字的shutdown
方法,如下所示:
s.shutdown(socket.SHUT_RDWR)
s.close()
这样它就不允许进一步发送/接收,查看有关它的Python文档,在那里很好地解释了。
更新:修复客户端代码
import socket
host = 'localhost'
port = 50000
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
msg = ''
while msg !='quit':
msg = raw_input()
s.send(msg)
#data = s.recv(size)
s.shutdown(socket.SHUT_RDWR)
s.close()