繁体   English   中英

Python 中的套接字错误:BlockingIOError:[Errno 35] 资源暂时不可用

[英]Socket Error in Python: BlockingIOError: [Errno 35] Resource temporarily unavailable

所以这里有问题。 我尝试在Python中使用socket实现一个简单的 Web 服务器。 单线程版本运行良好。 但是当我尝试使用非阻塞模式实现更多线程时,它会出现错误。我尝试在 Stackoverflow 和 Google 中搜索,但没有答案。 这是我的代码:

# coding:utf-8

import errno
import socket
import threading
import time

EOL1 = b'\n\n'
EOL2 = b'\n\r\n'
body = '''<h1>Hello, world!</h1> - from {thread_name}'''
response_params = [
    'HTTP/1.0 200 OK',
    'Date: Mon, 01 jan 2022 01:01:01 GMT'
    'Content-Type: text/plain; charset=utf-8',
    'Content_Length: {length}\r\n',
    body,
]
response = '\r\n'.join(response_params)


def handle_connection(conn, addr):
    # print(conn, addr)
    # time.sleep(60)
    request = b""
    while EOL1 and EOL2 not in request:
        request += conn.recv(1024)     # ERROR HERE!

    print(request)
    current_thread = threading.currentThread()
    content_length = len(body.format(thread_name=current_thread.name).encode())
    print(current_thread.name)
    conn.send(response.format(thread_name=current_thread.name,
                              length = content_length).encode())
    conn.close()


def main():
    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    serversocket.bind(('127.0.0.1', 8000))
    serversocket.listen(10)
    print('http://127.0.0.1:8000')
    serversocket.setblocking(0)

    try:
        i = 0
        while True:
            try:
                conn, address = serversocket.accept()
            except socket.error as e:
                if e.args[0] != errno.EAGAIN:
                    raise
                continue
            i += 1
            print(i)
            t = threading.Thread(target=handle_connection, args=(conn, address),
                                 name = 'thread-%s' % i)
            t.start()
    finally:
        serversocket.close()


if __name__ == '__main__':
    main()

错误消息在这里:

1
Exception in thread thread-1:
2
Traceback (most recent call last):
  File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 973, in _bootstrap_inner
Exception in thread thread-2:
Traceback (most recent call last):
  File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
    self.run()
  File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 910, in run
  File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/tdeveloper/Development/Learning/Python_Simple_WSGI/socket/thread_socketserver.py", line 26, in handle_connection
    self._target(*self._args, **self._kwargs)
  File "/Users/tdeveloper/Development/Learning/Python_Simple_WSGI/socket/thread_socketserver.py", line 26, in handle_connection
    request += conn.recv(1024)
BlockingIOError: [Errno 35] Resource temporarily unavailable
    request += conn.recv(1024)
BlockingIOError: [Errno 35] Resource temporarily unavailable

请帮我。 非常感谢。

这显然是关于非阻塞标志的 inheritance 的accept的 macOS 实现不同于其他平台的问题。 它与线程本身无关。

这是一个演示的精简单线程测试程序。

#!/usr/bin/env python3
import select
import socket

ssocket = socket.socket()
ssocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ssocket.bind(('127.0.0.1', 7000))
ssocket.listen(10)

ssocket.setblocking(0)       # <<<<<<<===========

select.select([ssocket], [], [])
csocket, caddr = ssocket.accept()
csocket.recv(10)

如果您在 linux 上运行它,并使用nc localhost 7000连接到它, csocket.recv会按您的预期阻塞。 在 macos 上运行相同的程序, recv会立即触发您看到的BlockingIOException

查看 macos 上的手册页accept(2)显示:

[...] 创建一个具有与套接字相同属性的新套接字

在这种情况下,非阻塞文件描述符标志( O_NONBLOCK )被新套接字“继承”。 因此,如果您不想要它,则需要使用conn.setblocking(1)在接受的套接字上禁用它。 显然,这种行为是由于 MacOS 源自 Unix 的 BSD 风格。

综上所述,您无需禁用阻塞,除非您的实际程序比显示的更多。 即,如果您的主线程除了接受连接之外什么都不做,然后分离一个单独的线程来处理连接,那么没有理由不让主线程阻塞在accept中。 如果您允许侦听套接字保持阻塞模式,则接受的 sockets 也应该处于阻塞模式。 (顺便说一句,你在那个主线程循环中浪费了大量的 CPU 时间:调用accept ,捕获异常,然后continue重新开始循环。)

(For clarity, my specs: python 3.7.3 downloaded from https://www.python.org/ftp/python/3.7.3/python-3.7.3-macosx10.9.pkg running on MacOS Catalina 10.15.7)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM