How to tell if a connection is dead in python

前端 未结 5 632
忘掉有多难
忘掉有多难 2020-11-29 23:41

I want my python application to be able to tell when the socket on the other side has been dropped. Is there a method for this?

5条回答
  •  没有蜡笔的小新
    2020-11-30 00:17

    I translated the code sample in this blog post into Python: How to detect when the client closes the connection?, and it works well for me:

    from ctypes import (
        CDLL, c_int, POINTER, Structure, c_void_p, c_size_t,
        c_short, c_ssize_t, c_char, ARRAY
    )
    
    
    __all__ = 'is_remote_alive',
    
    
    class pollfd(Structure):
        _fields_ = (
            ('fd', c_int),
            ('events', c_short),
            ('revents', c_short),
        )
    
    
    MSG_DONTWAIT = 0x40
    MSG_PEEK = 0x02
    
    EPOLLIN = 0x001
    EPOLLPRI = 0x002
    EPOLLRDNORM = 0x040
    
    libc = CDLL(None)
    
    recv = libc.recv
    recv.restype = c_ssize_t
    recv.argtypes = c_int, c_void_p, c_size_t, c_int
    
    poll = libc.poll
    poll.restype = c_int
    poll.argtypes = POINTER(pollfd), c_int, c_int
    
    
    class IsRemoteAlive:  # not needed, only for debugging
        def __init__(self, alive, msg):
            self.alive = alive
            self.msg = msg
    
        def __str__(self):
            return self.msg
    
        def __repr__(self):
            return 'IsRemoteClosed(%r,%r)' % (self.alive, self.msg)
    
        def __bool__(self):
            return self.alive
    
    
    def is_remote_alive(fd):
        fileno = getattr(fd, 'fileno', None)
        if fileno is not None:
            if hasattr(fileno, '__call__'):
                fd = fileno()
            else:
                fd = fileno
    
        p = pollfd(fd=fd, events=EPOLLIN|EPOLLPRI|EPOLLRDNORM, revents=0)
        result = poll(p, 1, 0)
        if not result:
            return IsRemoteAlive(True, 'empty')
    
        buf = ARRAY(c_char, 1)()
        result = recv(fd, buf, len(buf), MSG_DONTWAIT|MSG_PEEK)
        if result > 0:
            return IsRemoteAlive(True, 'readable')
        elif result == 0:
            return IsRemoteAlive(False, 'closed')
        else:
            return IsRemoteAlive(False, 'errored')
    

提交回复
热议问题