1

所以我在搞一个非常简单的回显服务器/客户端类型的交易。我最终会制作一个游戏服务器,但现在我只是尝试设置基本部分。

这是服务器: http: //pastebin.com/qtfrMGur

这是客户端:http: //pastebin.com/3VK3VxPX

所以,我的问题是,当客户端断开连接时,我得到 socket.error: [Errno 10054] An existing connection wasforced closed by the remote host。我的印象是,当可读的套接字列表没有待处理的信息时,select.select() 返回 false(或空列表,等等)。这似乎是错误的原因,但是如果客户端不再存在,为什么 select.select() 返回 true(在第 26 行)?当我尝试在第 27 行检索一些信息时发生实际错误。我对此感到非常困惑,假设套接字的客户端已关闭,它不应该只是返回 [],然后转到 else on第 31 行并销毁该客户端?

我真的不知道还要发布什么,这似乎是一个非常基本的问题,通常我使用更抽象的库,比如 twisted,这很容易,但是对于这个项目,我必须使用传统的 BSD 套接字。如果你们有任何其他信息需要,请询问。

谢谢。

编辑:所以我在那里放了一个打印语句来打印 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 中这样做。这是某种错误吗?我的印象是套接字库抽象了引擎盖下的所有东西,以使操作系统之间的接口相同。

4

1 回答 1

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()
于 2013-04-30T06:06:06.200 回答