简体   繁体   English

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

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

So Here is something wrong.所以这里有问题。 I try to implement a simple Web Server in Python use socket .我尝试在Python中使用socket实现一个简单的 Web 服务器。 The single-thread version runs well.单线程版本运行良好。 But when I try to implement more threads with non-blocking mode , it comes with errors.I try to search in Stackoverflow and Google, but no answers.但是当我尝试使用非阻塞模式实现更多线程时,它会出现错误。我尝试在 Stackoverflow 和 Google 中搜索,但没有答案。 Here is my code:这是我的代码:

# 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()

The Error message is here:错误消息在这里:

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

Please help me.请帮我。 Thanks a lot.非常感谢。

This is apparently an issue with the macos implementation of accept being different than that in other platforms with respect to inheritance of the non-blocking flag.这显然是关于非阻塞标志的 inheritance 的accept的 macOS 实现不同于其他平台的问题。 It has nothing to do with threading per se.它与线程本身无关。

Here's a trimmed-down single-threaded test program that demonstrates.这是一个演示的精简单线程测试程序。

#!/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)

If you run this on linux, and connect to it with nc localhost 7000 , the csocket.recv blocks as you're expecting.如果您在 linux 上运行它,并使用nc localhost 7000连接到它, csocket.recv会按您的预期阻塞。 Run the same program on macos and the recv immediately triggers the BlockingIOException you're seeing.在 macos 上运行相同的程序, recv会立即触发您看到的BlockingIOException

Looking at the manual page accept(2) on macos shows:查看 macos 上的手册页accept(2)显示:

[...] creates a new socket with the same properties of socket [...] 创建一个具有与套接字相同属性的新套接字

In this case, the non-blocking file descriptor flag ( O_NONBLOCK ) is being "inherited" by the new socket.在这种情况下,非阻塞文件描述符标志( O_NONBLOCK )被新套接字“继承”。 So if you don't want it, you'll need to disable it on the accepted socket with conn.setblocking(1) .因此,如果您不想要它,则需要使用conn.setblocking(1)在接受的套接字上禁用它。 Apparently this behavior is due to MacOS being descended from the BSD flavor of Unix.显然,这种行为是由于 MacOS 源自 Unix 的 BSD 风格。

All of that being said, you have no need to disable blocking anyway unless there is more to your actual program than shown.综上所述,您无需禁用阻塞,除非您的实际程序比显示的更多。 Ie if your main thread is doing nothing but accepting a connection and then spinning off a separate thread to handle the connection, there's no reason not to let the main thread just block in accept .即,如果您的主线程除了接受连接之外什么都不做,然后分离一个单独的线程来处理连接,那么没有理由不让主线程阻塞在accept中。 If you allow the listening socket to remain in blocking mode, the accepted sockets should also be in blocking mode.如果您允许侦听套接字保持阻塞模式,则接受的 sockets 也应该处于阻塞模式。 (By the way, as is, you're wasting a ton of CPU time in that main thread loop: calling accept , trapping the exception, then doing continue to start the loop over.) (顺便说一句,你在那个主线程循环中浪费了大量的 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) (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.

相关问题 BlockingIOError: [Errno 35] 资源暂时不可用 For Loop - BlockingIOError: [Errno 35] Resource temporarily unavailable For Loop BlockingIOError: [Errno 35] 资源暂时不可用 - BlockingIOError: [Errno 35] Resource temporarily unavailable Python Socket - [Errno 35] 资源暂时不可用 - Python Socket - [Errno 35] Resource temporarily unavailable 部署 Python Web 应用程序后出现 App Engine 错误 - BlockingIOError: [Errno 11] 资源暂时不可用 - App Engine error after Python web app is deployed - BlockingIOError: [Errno 11] Resource temporarily unavailable 使用PhantomJS,python,selenium,unittest“IOError:[Errno 35]资源暂时不可用” - “IOError: [Errno 35] Resource temporarily unavailable” with PhantomJS, python, selenium, unittest BlockingIOError: [Errno 11] 资源暂时不可用 两个客户端 一个服务器 sockets python - BlockingIOError: [Errno 11] Resource temporarily unavailable two clients one server sockets python 随机出现“ socket.error:[Errno 11]资源暂时不可用” - “socket.error: [Errno 11] Resource temporarily unavailable” appears randomly Python错误:发送图像时“socket.error:[Errno 11]资源暂时不可用” - Python error: “socket.error: [Errno 11] Resource temporarily unavailable” when sending image 如何防止出现“ OSError:[Errno 35] Resource暂时不可用”退出并行python? - How can I prevent parallel python from quitting with “OSError: [Errno 35] Resource temporarily unavailable”? h5py cant open file: BlockingIOError: [E 11] Unable to open file (unable to lock file, errno = 11, error message = '资源暂时不可用') - h5py cant open file: BlockingIOError: [E 11] Unable to open file (unable to lock file, errno = 11, error message = 'Resource temporarily unavailable')
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM