【问题标题】:readable socket times out on recvrecv 上的可读套接字超时
【发布时间】:2016-09-21 06:10:54
【问题描述】:

我有一个“作业”服务器,它接受来自客户端的请求(有 8 个客户端从另一台机器发送请求)。服务器然后提交一个“作业”(“作业”只是一个将结果文件写入磁盘的可执行文件),并且在“作业管理器”线程上等待直到作业完成。作业完成后,它会向客户端发送一条消息,表明结果文件已准备好复制回客户端。

在主线程上,我使用select 来读取来自客户端的传入连接以及作业请求:

readable, writable, exceptional = select.select(inputs, [], [])

其中inputs 是已接受连接(套接字)的列表,该列表还包括server 套接字。所有套接字都设置为非阻塞。据我所知,如果对select 的调用返回非空readable,这意味着inputs 的某些元素有等待读取的传入数据。 我正在使用以下逻辑读取数据(SIZE 是一个常量):

for s in readable:
    if s is not server:
        try:
            socket_ok = True
            data = s.recv(SIZE)
        except socket.error as e:        
            print ('ERROR socket error: ' + str(e) )
            socket_ok = False
        except Exception as e:
            print ('ERROR error reading from socket: ' + str(e))
            socket_ok = False
        if not socket_ok:
            # do something

我有两个问题:

  • 有时我得到一个[Errno 110] Connection timed out 异常,我不明白为什么 - 如果我有一个可读的套接字,这是否意味着它有一些数据要读取?
  • 如何处理这个异常 - #do something 部分。我可以做一个“清理”——删除超时套接字请求的正在运行的作业,并从列表中删除死套接字。但我无法让客户知道它应该停止等待这些工作的结果。理想情况下,我想以某种方式重新连接,因为作业本身会继续运行并产生我不想丢弃的结果。

编辑我现在意识到作业管理器线程也可以通过 Queue 实例访问套接字 - 如果作业完成,线程会通过相关的socket - 所以也许同一套接字的sendrecv 方法会导致某种竞争条件?但无论如何,我不明白这会如何导致“连接超时”错误。

【问题讨论】:

  • 尝试在此处阅读详细信息:pymotw.com/2/select
  • @ReutSharabani,我读过它,实际上我的代码是基于它的。但是您可以在我的代码中看到,从readbale 列表中的套接字读取时引发了异常,并且您提到的链接状态为All of the sockets in the readable list have incoming data buffered and available to be read - 所以这并不能解释我遇到的问题

标签: python sockets client-server


【解决方案1】:

一个只是猜测并且似乎有效的解决方案:在客户端,我使用阻塞 recv 方法从服务器获取工作完成的消息。由于作业可能需要很长时间(例如,如果运行作业的集群资源不足),我猜想可能是套接字等待是超时的原因。因此,我没有在阻塞模式下使用recv,而是在超时 5 秒的情况下使用它,因此我可以每 5 秒向服务器发送一条虚拟消息,以保持连接处于活动状态,直到收到消息为止。现在我不再得到异常(在服务器端)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 2019-08-18
    相关资源
    最近更新 更多