代码之家  ›  专栏  ›  技术社区  ›  Red Cricket

select()调用在调用setblocking(False)后仍处于阻塞状态

  •  0
  • Red Cricket  · 技术社区  · 4 年前

    我有一些服务器端代码:

        def listen_on_port(self):
    
            try:
                running = True
                HOST = ''                # Symbolic name meaning all available interfaces
                PORT = int(self.port)    # Arbitrary non-privileged port
                server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                server_socket.bind((HOST, PORT))
                server_socket.listen()
                server_socket.setblocking(False)  # non-blocking I/O
                self.logger.info(f'listening on port {self.port}')
                read_list = [server_socket]
                while running:
                   try:
                        self.logger.info(f'calling select().')
                        readable, writable, errored = select.select(read_list, [], [])
                        self.logger.info(f'called select().')
                        for s in readable:
                            if s is server_socket:
                                client_socket, address = server_socket.accept()
                                read_list.append(client_socket)
                                self.logger.info(f"Connection from address = {address} client_socket is {client_socket}.")
                            else:
                                self.logger.info(f"going to call s.recv(). s is {s}")
                                try:
                                    data = s.recv(1024)
                                    self.logger.info(f"Got data = {data}.")
                                    if 'terminate' in data.decode('utf-8'):
                                        self.logger.info(f"terminating.")
                                        running = False
                                except Exception as ex:
                                    self.logger.info(f'error s.recv() ex={ex}.')
                                finally:
                                    self.logger.info(f"closing socket. s = {s}.")
                                    s.close()
                                    read_list.remove(s)
                   except Exception as ex:
                       self.logger.info(f'Inside while True. error ex={ex}.')
                       raise ex
            except Exception as ex:
                self.logger.info(f'error ex={ex}.')
    

    当我运行脚本时,我可以在日志文件中看到我的代码正在等待。。。

    readable, writable, errored = select.select(read_list, [], [])
    

    ... 回来。我的日志文件:

    $ cat /tmp/test.log    
    doing port 50050
    listening on port 50050
    calling select().
    

    我打电话给。。。

    server_socket.setblocking(False)  # non-blocking I/O
    

    ... 但代码仍然阻塞。如果这很重要的话,我是在mac(而不是Linux系统)上运行的。

    1 回复  |  直到 4 年前
        1
  •  1
  •   user2357112    4 年前

    select 不管插座是否阻塞。如果你想做一个非阻塞 选择 调用时,需要指定0的超时值:

    readable, writable, errored = select.select(read_list, [], [], 0)
    

    也就是说,你的代码并没有什么比阻塞更好的事情要做。指定 timeout=0 就要把你的 while running 循环进入忙碌的等待。

    推荐文章