多线程处理多个传入请求

时间:2016-10-13 14:36:39

标签: python multithreading sockets

我是python的新手。我必须编写一个侦听器/服务器来处理来自同一网络的请求。所以我使用的是socket。我将从客户端获取请求json,服务器/监听器将进行处理并返回结果。这就是将要发生的一切。并且服务器和客户端之间不会进行来回通信。

代码看起来像这样:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    
server_address = ('localhost', 10000)            
sock.bind(server_address)    
sock.listen(1)

while True: 
    connection, client_address = sock.accept()

    while True:
        #read request data
        #process request 
        #reply response to **connection** object
        break  #continue waiting for new request

现在的问题是,在当前请求的处理完成之前,服务器将不接受新请求。我不知何故必须在单独的并发线程中执行处理和发送响应回复。我尝试将处理逻辑封装在扩展RequestHandler类的单独的类Thread中。我将connection对象传递给了我的自定义类RequestHandler的实例。 我做了这样的事情:

requestHandler = RequestHandler(deepcopy(connection))
requestHandler.daemon = True
requestHandler.start()  

然而,这是我陷入困境的地方。我是否可以将相同的connection对象传递给每次收到新请求时产生的新实例RequestHandler?如上面代码中的深度复制给了我以下错误:

TypeError: Cannot serialize socket object

我做错了什么?我应该采用一些不同的方法吗?

1 个答案:

答案 0 :(得分:1)

无需延长Thread课程。最简单的版本是:

import threading

def client_handler(connection):
    #read request data
    #process request 
    #reply response to **connection** object

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    
server_address = ('localhost', 10000)            
sock.bind(server_address)    
sock.listen(1)

while True: 
    connection, client_address = sock.accept()
    threading.Thread(target=client_handler, args=(connection,)).start()

现在你可以将你的套接字对象包装到RequestHandler类中,如果你愿意,那很好。但你无法复制套接字。只需传递引用:RequestHandler(connection)。你还为什么要复制它?

它不可复制的原因是因为它代表了一些系统资源(即套接字)。如果有2个对象指向同一个资源,那么它们会相互冲突。在C级别,如果有多个所有者,则很难同步纯文件描述符(套接字只是C级别的数字)。因此,套接字对象是底层文件描述符的唯一“网关”。