![](/img/trans.png)
[英]BlockingIOError: [Errno 35] Resource temporarily unavailable For Loop
[英]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.