带有线程池服务器python的套接字

Posted

技术标签:

【中文标题】带有线程池服务器python的套接字【英文标题】:sockets with threadpool server python 【发布时间】:2017-05-29 22:15:41 【问题描述】:

我有一个简单的多线程服务器,但它为每个套接字创建一个新线程,我不想创建很多线程。我的想法是以其他方式接收消息:当用户发送消息时,它会将消息添加到消息队列中,服务器将使用线程池处理这些请求。

简单的多线程服务器:

import socket
import threading

class ThreadedServer(object):
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind((self.host, self.port))

    def listen(self):
        self.sock.listen(5)
        while True:
            client, address = self.sock.accept()
            client.settimeout(60)
            threading.Thread(target = self.listenToClient,args = (client,address)).start()

    def listenToClient(self, client, address):
        size = 1024
        while True:
            try:
                data = client.recv(size)
                if data:
                    # Set the response to echo back the recieved data 
                    response = data
                    client.send(response)
                else:
                    raise error('Client disconnected')
            except:
                client.close()
                return False

if __name__ == "__main__":
    port_num = input("Port? ")
    ThreadedServer('',port_num).listen()

如何实现我的想法或有更好的方法来实现它?

【问题讨论】:

我建议使用socketserver docs.python.org/3.6/library/socketserver.html 【参考方案1】:

这个问题似乎很老了,但我在处理套接字服务器时也偶然发现了同样的问题,所以这里是下面的代码,您可以使用它来制作线程套接字服务器,它在到达时不会产生新线程。

只是为了给出要点 ThreadingMixIn 类被线程池覆盖。

class ThreadPoolMixIn(socketserver.ThreadingMixIn):
'''
use a thread pool instead of a new thread on every request
'''
# numThreads = 50    
allow_reuse_address = True  # seems to fix socket.error on server restart
def serve_forever(self):
    '''
    Handle one request at a time until doomsday.
    '''
    print('[X] Server is Running with No of Threads :- '.format(self.numThreads))
    # set up the threadpool
    self.requests = Queue(self.numThreads)

    for x in range(self.numThreads):
        t = threading.Thread(target = self.process_request_thread)
        t.setDaemon(1)
        t.start()

    # server main loop
    while True:
        self.handle_request()
    self.server_close()

def process_request_thread(self):
    '''
    obtain request from queue instead of directly from server socket
    '''
    while True:
        socketserver.ThreadingMixIn.process_request_thread(self, *self.requests.get())

def handle_request(self):
    '''
    simply collect requests and put them on the queue for the workers.
    '''
    try:
        request, client_address = self.get_request()
    except socket.error:
        return
    if self.verify_request(request, client_address):
        self.requests.put((request, client_address))

然后在ThreadedTCPRequest Handler中调用并覆盖numThreads参数:

class ThreadedTCPServer(ThreadPoolMixIn, socketserver.TCPServer):
#Extend base class and overide the thread paramter to control the number of threads.
def __init__(self, no_of_threads, server_address, ThreadedTCPRequestHandler):
    self.numThreads = no_of_threads
    super().__init__(server_address, ThreadedTCPRequestHandler)

最终创建永远服务的服务器:

def create_multi_threaded_socket(CONFIG, HandlerClass = ThreadedTCPRequestHandler,
    ServerClass = ThreadedTCPServer, 
    protocol="HTTP/1.0"):

server_address = ('', CONFIG.port)
HandlerClass.protocol_version = protocol
# httpd = ServerClass(server_address, HandlerClass)
server = ThreadedTCPServer(CONFIG.no_of_threads, server_address, ThreadedTCPRequestHandler)
sa = server.socket.getsockname()
print("Serving HTTP on  port : ".format(sa[0], sa[1]))
server.serve_forever()

我的示例代码来自: http://code.activestate.com/recipes/574454-thread-pool-mixin-class-for-use-with-socketservert/

根据我的需要进行了修改。 希望这会有所帮助:)。

【讨论】:

以上是关于带有线程池服务器python的套接字的主要内容,如果未能解决你的问题,请参考以下文章

python全栈脱产第37天------进程池与线程池协程gevent模块单线程下实现并发的套接字通信

Linux网络(C++)——网络套接字(TCP/UDP编程模型)多进程,多线程,线程池服务器开发(画图解析)

Java Web应用中调优线程池的重要性

转:Java Web应用中调优线程池的重要性

进程池与线程池

Java Web应用中调优线程池的重要性