【问题标题】:Python Socket Library, Errno 10054 When Client QuitsPython Socket 库,客户端退出时出现 Errno 10054
【发布时间】:2013-05-01 06:13:39
【问题描述】:

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

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

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

所以,我的问题是,当客户端断开连接时,我得到 socket.error: [Errno 10054] 现有连接被远程主机强行关闭。我的印象是,当可读的套接字列表没有待处理的信息时,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 中它才会这样做。这是某种错误吗?我的印象是套接字库抽象了引擎盖下的所有东西,以使操作系统之间的接口相同。

【问题讨论】:

  • 只是一个想法,但也许这是一个竞争条件。 recv 可以返回一个客户端,同时该客户端可能会断开连接。不过看起来你一定很倒霉。
  • 我不认为这是一个竞争条件,我在那里打印了一些打印来诊断问题,似乎 select.select() 在客户端退出时正在返回客户端套接字。就好像客户端有一些最后的消息功能,当它死时它会发送一些信息。

标签: python sockets client host errno


【解决方案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()

【讨论】:

  • 我补充说,仍然抛出 Errno 10054。我一直在打印 select.select([cl], [], [], 0)[0] 每次的结果,它返回 [ ],直到我退出客户端,在这种情况下它返回客户端。没有任何意义,为什么 cl.recv(size) 会在客户端关闭并关闭时正确返回客户端?
  • 好的,但是关闭方法也必须在客户端调用。实际上,即使您仅在客户端调用它也不会引发错误,但最好在双方都调用它。我会用固定的客户端代码更新我的答案。
  • 我一直都在调用它。如果有一种简单的方法可以检测到客户端已断开连接。
猜你喜欢
  • 2016-05-30
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
  • 1970-01-01
  • 2020-10-27
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多