Detect why a socket closed: FIN vs RST

Viewed 644

Is it possible to detect why a socket closed in Python, i.e. whether the other side sent a FIN or an RST?

The only way I know to detect if the other side has senta FIN or RST, is to read from the socket, and if you get the empty (byte) string, then we have received either a FIN or an RST. But how to know which one?

import asyncio
import socket

async def async_main(loop):

    server_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM,
                                proto=socket.IPPROTO_TCP)
    server_sock.setblocking(False)
    server_sock.bind(('', 8080))
    server_sock.listen(socket.IPPROTO_TCP)

    loop = asyncio.get_event_loop()
    sock, adddress = await loop.sock_accept(server_sock)

    while True:
        data = await loop.sock_recv(sock, 1024)
        if data == b'':
            # Socket closed, but how?
            break
        print(data)

loop = asyncio.get_event_loop()
loop.run_until_complete(async_main(loop))
1 Answers

Based on James K Polk's comment, which I believe to be correct, you would distinguish FIN from RST by catching the appropriate exception:

    while True:
        is_rst = False
        try:
            data = await loop.sock_recv(sock, 1024)
        except IOError as e:
            if e.errno == errno.ECONNRESET:
                data = b''
                is_rst = True
            else:
               raise
        if data == b'':
            # Connection closed - use is_rst to distinguish
            # between RST and FIN
            break
        print(data)
Related