客户端退出时,Python套接字库,Errno 10054

Python Socket Library, Errno 10054 When Client Quits

所以我正在搞乱一个非常简单的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]的值,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
"

                clients.remove(cl)
                cl.shutdown(socket.SHUT_RDWR)
                cl.close()
                print len(clients)

如你所见,我现在也正确关机。问题是,当客户端退出时,select.select(...)将客户端套接字作为可读源返回,因此cl.recv被调用,然后抛出错误,因为cl在另一端关闭。至少这是我的怀疑。

那么,有人可以解释一下我在这里做错了什么吗?为什么客户端发送最后一条死亡消息,是否应该利用某种功能?

谢谢

EDIT2:所以大家我启动了我的debian机器,代码运行完美,它只在Windows中才能正常运行。这是某种错误吗?我的印象是套接字库抽象了引擎盖下的所有东西,使得OS之间的界面相同。


你应该在客户端关闭它之前调用套接字的shutdown方法,如下所示:

1
2
s.shutdown(socket.SHUT_RDWR)
s.close()

这样它就不允许进一步发送/接收,查看有关它的Python文档,它在那里得到了很好的解释。

更新:修复客户端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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()