簡體   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