当前位置:  开发笔记 > 编程语言 > 正文

如何在python中处理损坏的管道(SIGPIPE)?

如何解决《如何在python中处理损坏的管道(SIGPIPE)?》经验,为你挑选了2个好方法。

我在python中编写了一个简单的多线程游戏服务器,为每个客户端连接创建一个新线程.我发现时不时,服务器会因为管道损坏/ SIGPIPE错误而崩溃.当程序试图将响应发送回不再存在的客户端时,我非常确定它正在发生.

处理这个问题的好方法是什么?我的首选解决方案只是关闭与客户端的服务器端连接并继续,而不是退出整个程序.

PS:这个问题/答案以一般方式处理问题; 具体应该如何解决?



1> mhawke..:

假设您正在使用标准套接字模块,您应该捕获socket.error: (32, 'Broken pipe')异常(而不是其他人建议的IOError).这将在您描述的情况下引发,即发送/写入远程端已断开连接的套接字.

import socket, errno, time

# setup socket to listen for incoming connections
s = socket.socket()
s.bind(('localhost', 1234))
s.listen(1)
remote, address = s.accept()

print "Got connection from: ", address

while 1:
    try:
        remote.send("message to peer\n")
        time.sleep(1)
    except socket.error, e:
        if isinstance(e.args, tuple):
            print "errno is %d" % e[0]
            if e[0] == errno.EPIPE:
               # remote peer disconnected
               print "Detected remote disconnect"
            else:
               # determine and handle different error
               pass
        else:
            print "socket error ", e
        remote.close()
        break
    except IOError, e:
        # Hmmm, Can IOError actually be raised by the socket module?
        print "Got IOError: ", e
        break

请注意,在第一次写入闭合套接字时不会总是引发此异常 - 通常是第二次写入(除非第一次写入中写入的字节数大于套接字的缓冲区大小).您需要记住这一点,以防您的应用程序认为远程端在可能已断开连接时收到第一次写入的数据.

您可以通过使用select.select()(或poll)来减少这种情况(但不是完全消除).在尝试写入之前,检查准备从对等方读取的数据.如果select报告有可从对等套接字读取的数据,请使用它进行读取socket.recv().如果返回空字符串,则远程对等方已关闭连接.因为这里仍然存在竞争条件,所以您仍然需要捕获并处理异常.

扭曲对于这种事情是很好的,但是,听起来你已经编写了相当多的代码.



2> S.Lott..:

阅读try:语句.

try:
    # do something
except socket.error, e:
    # A socket error
except IOError, e:
    if e.errno == errno.EPIPE:
        # EPIPE error
    else:
        # Other error


对于损坏的管道套接字异常,您不会使用errno == EPIPE获取IOError,您将获得socket.error,因此在IOError异常处理程序中检查它是没有意义的.你有2票赞成(仍然)不好的答案.也许你应该投票我的答案:)
毯子除了是一个糟糕的政策.但是,它会遇到任何异常.你知道这是一个IOError.处理那个.如果出现其他问题,找出原因并妥善处理.你不想掩盖像零除或内存不足的错误.
同意提问者现在应该知道该怎么做.您的代码段仍然不正确,提问者可能会按照您的示例进行操作.它不会破坏他的代码,只是在IOError处理程序中检查EPIPE是没用的.
@mhawke:你还是对的.两次.但是,很难设计标准操作系统错误(使用errno)和其他错误(没有错误)的示例.我认为有一个整洁的代码示例很重要 - 我不是为他们编写应用程序.
推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有