【问题标题】:Send socket object to forked running process (multiprocessing.Queue)将套接字对象发送到分叉的运行进程(multiprocessing.Queue)
【发布时间】:2012-06-03 01:40:19
【问题描述】:

我正在学习使用 HTML5 WebSockets,作为其中的一部分,我正在用 Python 编写一个服务器,这样我就可以了解它们的工作原理。前几天我创建了一个运行良好的,但我想扩展它,以便它支持多个端点,每个端点都是可以处理 websocket 客户端的不同“服务”。

目前,我的实现适用于生成进程等(我使用多处理而不是线程,因为我读到线程在 CPython 中并不是真正的多线程,这就是我认为我正在使用的(默认安装在 Ubuntu 12.04 上) ),但我无法将收到的客户端套接字发送到服务进程。

这是我发送它们的方式(循环运行):

try:
    #get a new client
    conn, addr = server.accept()
    print "Client connected from", addr
    request = conn.recv(4096)
    response, close, service = self.handshake(request)
    conn.send(response)
    if close:
        print "Invalid request from", addr
        conn.close()
        continue
    client = WebSockets.WebSocketClient(conn, addr)
    service.clientConnQueue.put(client)

'server' 是一个侦听传入连接的套接字。握手方法负责验证他们的请求并确定将客户端放入哪个服务进程。 'response' 是发送的 http 响应,'close' 是 True 如果有错误,'service' 是一个继承自 multiprocessing.Queue 的类。 WebSocktes.WebSocketClient 是存储我的发送和接收实现的地方,它基本上用作套接字的包装器。

'clientConnQueue' 是这样创建的:

class Service(multiprocessing.Process):
    """Base class for all services."""
    def __init__(self, manager):
        multiprocessing.Process.__init__(self)
        self.manager = manager
        self.clientConnQueue = self.manager.Queue()
        self.shutdownFlag = multiprocessing.Event()

manager 是一个 multiprocessing.Manager()

当我尝试将客户端放入 clientConnQueue 时出现的错误如下:

File "./WebSocketServer.py", line 183, in <module>
main()
File "./WebSocketServer.py", line 180, in main
server.runServer()
File "./WebSocketServer.py", line 67, in runServer
service.clientConnQueue.put(client)
File "<string>", line 2, in put
File "/usr/lib/python2.7/multiprocessing/managers.py", line 758, in _callmethod
conn.send((self._id, methodname, args, kwds))
TypeError: expected string or Unicode object, NoneType found

然后我在接收端收到一个损坏的管道错误。

我在使用 multiprocessing.Queue 发送连接时遇到了同样的错误,我认为将其更改为由管理器创建的队列可以解决问题。但是,它似乎执行完全相同的实现。

显然,这不是向正在运行的进程发送此类内容的方式,那么将不可序列化的对象发送到进程的正确方法是什么?

【问题讨论】:

    标签: python sockets queue multiprocessing


    【解决方案1】:

    将套接字传递给另一个进程并不是一件小事。例如,看这个问题: Can I open a socket and pass it to another process in Linux

    无论如何,OS 进程或线程并不是你真正想要实现 websocket 服务器的,因为内存开销很大。用非阻塞套接字看看……例如,Tornado http://www.tornadoweb.org/documentation/websocket.html

    【讨论】:

    • 每个客户端套接字不一定有自己的线程,但每个服务确实有自己的进程/线程,具体如何处理套接字由服务决定。这是一个很好的观点……http 服务器不必处理同时存在 1000 个长寿命连接的可能性,如果每个连接都有自己的线程,那将是大量的内存开销。
    【解决方案2】:

    它已经存在了 4 年多,虽然需要一些工作。

    胆量在 multiprocessing.reduction 中徘徊,示例的细节可以在this github gist 中看到。

    【讨论】:

      【解决方案3】:

      如果不使用深层次的 unix 魔法,就无法将套接字发送到分叉的进程。如果您真的想了解它是如何在 C 中完成的,您可以阅读《Unix 环境中的高级编程》一书。

      对于使用线程的简单解决方案更改,您的代码可能会正常工作。虽然 Python 中的线程并不完美,但它非常适合执行 IO 密集型工作。

      或者在分叉之前创建你的监听套接字并让所有子进程监听(调用accept)。操作系统将确保只有其中一个获得连接。这是通常编写预分叉服务器的方式。

      【讨论】:

        【解决方案4】:

        如果你在进程分叉之前创建套接字,那么它的文件描述符将被子进程继承。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-04-11
          • 2020-05-06
          • 2013-04-09
          • 2011-02-10
          • 1970-01-01
          • 2011-02-14
          • 2012-03-13
          相关资源
          最近更新 更多