POLLHUP vs. POLLRDHUP?

Q:

According to the poll man page, the poll function can return POLLHUP and POLLRDHUP events. From what I understand, only POLLHUP is POSIX compliant, and POLLRDHUP is a Linux non-standard extension. Howerver, both seem to signal that the write end of a connection is closed, so I don't understand the added value of POLLRDHUP over POLLHUP. Would someone please explain the difference between the two?

A:

No, when poll()ing a socket, POLLHUP will signal that the connection was closed in both directions.

POLLRDHUP will be set when the other end has called shutdown(SHUT_WR) or when this end has called shutdown(SHUT_RD), but the connection may still be alive in the other direction.

You can have a look at net/ipv4/tcp.c the kernel source:

        if (sk->sk_shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
                mask |= EPOLLHUP;
        if (sk->sk_shutdown & RCV_SHUTDOWN)
                mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;

SHUTDOWN_MASK is RCV_SHUTDOWN|SEND_SHUTDOWNRCV_SHUTDOWN is set when a FIN packet is received, and SEND_SHUTDOWN is set when a FIN packet is acknowledged by the other end, and the socket moves to the FIN-WAIT2 state.

[except for the TCP_CLOSE part, that snippet is replicated by all protocols; and the whole thing works similarly for unix sockets, etc]

There are other important differences -- POLLRDHUP (unlike POLLHUP) has to be set explicitly in .events in order to be returned in .revents.

And POLLRDHUP only works on sockets, not on fifos/pipes or ttys.

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Python 中,使用 `socket` 模块创建的 `socket.socket` 对象可以通过 `close()` 方法来关闭。如果你要监听 socket 对象的关闭事件,可以使用 `select` 模块中的 `select()` 函数,该函数可以监视一组文件描述符(包括 socket 对象),并在其中任何一个文件描述符上发生事件时返回。在监听 socket 关闭事件时,你可以将 socket 对象的文件描述符添加到 `select()` 函数的监视列表中,然后在函数返回后检查该 socket 对象是否异常关闭(即是否出现了 `select.POLLHUP` 或 `select.POLLERR` 事件),如果出现了异常事件,则说明该 socket 对象已经关闭。下面是一个简单的示例代码: ```python import socket import select server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('localhost', 12345)) server_socket.listen(5) # 将 server socket 对象的文件描述符添加到监视列表中 poll = select.poll() poll.register(server_socket.fileno(), select.POLLIN | select.POLLHUP | select.POLLERR) while True: # 等待事件发生 events = poll.poll() for fileno, event in events: if fileno == server_socket.fileno(): # 接收到客户端连接请求 client_socket, client_address = server_socket.accept() print('New client connected:', client_address) # 将新的 client socket 对象的文件描述符添加到监视列表中 poll.register(client_socket.fileno(), select.POLLIN | select.POLLHUP | select.POLLERR) else: # 读取客户端发送的数据 client_socket = socket.fromfd(fileno, socket.AF_INET, socket.SOCK_STREAM) data = client_socket.recv(1024) if not data: # 检查 socket 对象是否异常关闭 if event & (select.POLLHUP | select.POLLERR): print('Client closed:', client_socket.getpeername()) else: print('Client disconnected:', client_socket.getpeername()) # 将 client socket 对象的文件描述符从监视列表中移除 poll.unregister(fileno) client_socket.close() else: print('Received data from', client_socket.getpeername(), ':', data.decode()) ``` 该示例代码中使用了 `select.poll()` 函数来监听 socket 对象的事件,如果事件包括 `select.POLLHUP` 或 `select.POLLERR`,则说明该 socket 对象已经关闭。注意,在检查 socket 对象是否异常关闭时,需要使用 `socket.fromfd()` 函数从文件描述符获取 socket 对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值