将套接字对象发送到分叉运行进程(multiprocessing.Queue)

时间:2012-05-28 18:18:03

标签: python sockets queue multiprocessing

我正在学习使用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发送连接时,我遇到了同样的错误,我认为将其更改为由管理员创建的队列可以解决问题。但是,它似乎执行完全相同的实现。

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

4 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

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

gull在multiprocessing.reduction中徘徊,可以在this github gist中看到示例的详细信息。

答案 2 :(得分:0)

如果不使用深度unix魔法,则无法将套接字发送到分叉进程。如果你真的想看看它是如何在C语言中完成的,你可以在Unix环境中阅读“高级编程”一书。

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

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

答案 3 :(得分:0)

如果在进程分叉之前创建套接字,则子文件将继承其文件描述符。