【问题标题】:Why is `select()` returning a client as writable when the client has disconnected?为什么当客户端断开连接时,`select()` 会将客户端返回为可写的?
【发布时间】:2019-03-05 22:39:55
【问题描述】:

我正在实现这个example,以便在一个简单的回显服务器中使用select。一切正常,客户端发送消息,接收回显并断开连接。

这是我用于客户端的代码:

import socket

ECHOER_PORT = 10000

if __name__ == '__main__':
    sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sockfd.connect(('localhost', ECHOER_PORT))

    msg = input('Message: ').encode()

    sockfd.send(msg)
    response = sockfd.recv(len(msg))
    print('Response: {}'.format(response))
    sockfd.close()

问题出在服务器上(完整的 gist 代码是 here),在发送回显后,再次调用 select 并且当前客户端(收到回显并断开连接)从选择返回可读可写。

我理解为什么它被返回为可读,因为根据文章:

没有可用数据的可读套接字来自具有 已断开连接,并且流已准备好关闭。

但我的问题是为什么 return 也是可写的?

【问题讨论】:

    标签: python sockets select network-programming


    【解决方案1】:

    但我的问题是为什么 return 也是可写的?

    当客户端断开连接时,您想让select() 做的主要事情是立即返回,以便您的代码可以检测到断开连接事件并尽快处理它(通过关闭套接字)。

    执行此操作的一种方法是常用方法,让服务器在每个套接字上选择读取,当客户端断开连接时,select() 将在该套接字上返回准备读取,然后程序将在socket上调用recv()查看数据是什么,recv()会返回EOF,服务器会关闭socket。这一切都很好。

    现在想象一种不太常见(但并非闻所未闻)的情况,即服务器写入其客户端套接字,但不想从中读取。在这种情况下,服务器不需要(或希望)在其套接字上选择准备读取;它只需要选择准备写入,以了解何时有一些传出数据缓冲区空间可用于向客户端发送更多数据。但是,该服务器仍然需要知道客户端何时断开连接 - 这就是断开连接的套接字也选择为准备写入的原因,因此仅监视准备写入的 select() 也可以检测到并立即对断开的套接字做出反应。

    【讨论】:

    • 但是它如何检测到客户端已经通过写操作断开连接?
    • 默认情况下(至少在 posix 风格的操作系统中)会引发 SIGPIPE 信号。或者,如果您的程序已将自己设置为忽略/禁用 SIGPIPE,则 send()/write() 将返回 -1 并将 errno 设置为 EPIPE。
    猜你喜欢
    • 2010-11-01
    • 1970-01-01
    • 2020-07-21
    • 2017-01-25
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    相关资源
    最近更新 更多