Python处理多个客户端连接---线程服务器
2016-05-19 22:38
645 查看
派生服务器的限制
一般来说,刚才描述的分支模型(派生服务器)在类unix平台上运行良好,但是会受一些隐藏的重要限制的影响:1.性能
在某些机器上,启动一个新的进程,在时间和空间资源方面的消耗特别大。2.可移植性
目前的os.fork调用在类似windows那样的非unix平台上不能运行。3.复杂性
分支会带来管理和捕获僵尸进程的所有方法—清理存在时间比它们的父进程少的子进程线程
解决所有这些难题的一个方案就是使用线程而不是进程。线程可以并行运行和共享全局内存。因为所有线程都运行在同一进程和内存空间中,所以它们自动共享它们之间传递的套接字,其核心类似于子进程继承套接字描述符的方式。然而,和进程不一样,线程的启动通常耗费不大,而且,如今可以运行在类unix机器和标准python下的windows上。此外,很多人认为线程是程序的简化形式—在退出时,子线程会静静的消失,不会留下在服务器上出没的僵尸进程。__author__ = 'JianqingJiang' # -*- coding: utf-8 -*- import time,_thread as thread # use threading.Thread().start() from socket import * myHost = '' myPort = 50007 sockobj = socket(AF_INET,SOCK_STREAM) # make a TCP socket object sockobj.bind((myHost,myPort)) # bind it to server port number sockobj.listen(5) # allow 5 pending connects def now(): return time.ctime(time.time()) # current time on server def handleClient(connection): # child process: reply,exit time.sleep(5) # simulate a blocking activity while True: # read , write a client socket data = connection.recv(1024) # till eof when socket closed if not data : break reply = 'Echo=>%s at %s' % (data,now()) connection.send(reply.encode()) connection.close() def dispatcher(): # listen until process killed while True: # wait for next connection connection,address = socket.accept() # pass to process for service print('Server connected by', address, end = ' ' ) print('at',now()) thread.start_new_thread(handleClient,(connection,)) dispatcher()
该dispatcher程序把每个传入的客户端连接请求,指定到新派生的运行handleClient函数的线程中。因此,该服务器可以同时处理多个客户端,主要的调度程序循环可以迅速回到顶端,以便检查新到达的请求。最终的效果就是,新的客户端就不会因服务器繁忙而拒绝服务。
当线程运行函数返回时,线程会默默的退出;不同于进程的fork类型,我们在客户端处理函数上不调用类似os._exit的命令(它可以关闭进程中的所有线程,包括监听新连接的主循环!)。正因为如此,线程类似不仅具有可移植性,也更加简单。
标准库服务器类
socketserver模块定义了可以实现所有你可能会感兴趣的各种分支和线程服务器的类。这个模块可以实现服务器的并行处理客户端,以避免在长期运行的事务中,拒绝服务器新的请求。为了使用这个模块,只需创建所需的导入服务器对象类型,通过自身的回调方法传入处理器对象__author__ = 'JianqingJiang' # -*- coding: utf-8 -*- import socketserver,time # get socket server,handler object myHost = '' myPort = 50007 sockobj = socket(AF_INET,SOCK_STREAM) # make a TCP socket object sockobj.bind((myHost,myPort)) # bind it to server port number sockobj.listen(5) # allow 5 pending connects def now(): return time.ctime(time.time()) # current time on server class MyClientHandler(socketserver.BaseRequestHandler): def handleClient(self): # child process: reply,exit print(self.client_address,now()) # show this client's address time.sleep(5) # simulate a blocking activity while True: # read , write a client socket data = connection.recv(1024) # till eof when socket closed if not data : break reply = 'Echo=>%s at %s' % (data,now()) self.request.send(reply.encode()) self.request.close() # make a threaded server,listen.handle clients forever myaddr = (myHost,myPort) server = socketserver.ThreadingTCPServer(myaddr,MyClientHandler) server.serve_forever()
这个服务器于我们手写的线程服务器一样运行,但是相反,它侧重于服务的实现(定制的handle方法),而不是线程细节。它也以同样的方式运行。
相关文章推荐
- PySide——Python图形化界面入门教程(六)
- python中的行结构和缩进
- pycharm安装图解
- python的二维数组操作
- Python map reduce
- LeetCode Insertion Sort List
- LeetCode Word Break II
- Python中__name__=="__main__"的作用
- Python实战_2_第一周_第三节课程:真实世界中的网页解析
- 【Python】测算代码运行时间
- 机器学习算法与Python实践之(四)支持向量机(SVM)实现
- python join与split函数的用法举例
- Python教程:[69]strip()函数详解
- selenium+python笔记5
- selenium+python笔记4
- python学习笔记-Day2
- python 源码解读2
- python学习笔记(2)--------Numpy
- [LeetCode][Python]Intersection of Two Arrays
- 深入super,看Python如何解决钻石继承难题