设为首页 收藏本站
查看: 494|回复: 0

[经验分享] Python的网络编程(四)

[复制链接]

尚未签到

发表于 2017-4-29 11:34:17 | 显示全部楼层 |阅读模式
   
使用SocketServers


SocketServers模块为一组socket服务类定义了一个基类,这组类压缩和隐藏了监听、接受和处理进入的socket连接的细节。

1、SocketServers家族
TCPServer和UDPServer都是SocketServer的子类,它们分别处理TCP和UDP信息。
注意:SocketServer也提供UnixStreamServer(TCPServer的子类)和UNIXdatagramServer(UDPServer的子类),它们都如同其父类一样除了在创建监听socket时使用AF_UNIX代替了AF_INET。

默认情况下,socket服务一次处理一个连接,但是你可以使用ThreadingMixIN和ForkingMixIn类来创建任一SocketServer的线程和子进程。实际上,SocketServer模块提供了一些对些有用的类来解决你的麻烦,它们是:ForkingUDPServer、ForkingTCPServer、ThreadingUDPServer、ThreadingTCPServer、ThreadingUnixStreamServer和ThreadingUnixDatagramServer。

SocketServer以通常的方法处理进入的连接;要使它更有用,你应该提供你自己的请求处理器类给它以便它传递一个socket去处理。SocketServer模块中的BaseRequestHandler类是所有请求处理器的父类。假设,例如你需要写一个多线程的电子邮件服务器,首先你要创建一个MailRequestHandler,它是BaseRequestHandler的子类,然后把它传递给一个新创建的SocketServer:
import SocketServer
...#创建你的MailRequestHandler
addr=('220.172.20.6',25) #监听的地址和端口
server=SocketServer.ThreadingTCPServer(addr,MailRequestHandler)
server.serve_forever()


每次一个新的连接到来时,这个server创建一个新的MailRequestHandler实例并调用它的handle()方法来处理这个新的请求。因为server继承自ThreadingTCPServer,对于每个新的请求它都启动一个单独的线程来处理这个请求,以便于多个请求能够被同时处理。如果用handle_request()代替server_forever,它将一个一个的处理连接请求。server_forever 只是反复调用handle_request而已。

一般来说,你只需使用socket服务之一,但是如果你需要创建你自己的子类的话,你可以覆盖我们下面提到的方法来定制它。

当服务被第一次创建的时候,__init__函数调用server_bind()方法来绑定监听socket(self.socket)到正确的地址(self.server_address)。然后调用server_activate()来激活这个服务(默认情况下,调用socket的listen方法)。

这个socket服务不做任何事情直到调用了handle_request或serve_forever方法。handle_request调用get_request()去等待和接收一个新的socket连接,然后调用verify_request(request,client_address)去看服务是否会处理这个连接(你可以在访问控制中使用这个,默认情况下verify_request总是返回true)。如果会处理这个请求,handle_request然后调用process_request(request,client_address),如果process_request(request,client_address)导致一个异常的话,将调用handle_error(request,client_address)。默认情况下,process_request简单地调用finish_request(request,client_address);子进程和线程类覆盖了这个行为去开始一新的进程或线程,然后调用finish_request。finish_request实例化一个新的请求处理器,请求处理器轮流调用它们的handle()方法。

当SocketServer创建一个新的请求处理器时,它传递给这个处理器的__init__函数的self变量,以便于这个处理器能够访问关于这个服务的信息。

SocketServer的fileno()方法返回监听socket的文件描述符。address_family成员变量指定了监听socket的socket族(如AF_INET),server_address包含了监听socket被绑定到的地址。socket变量包含监听socket自身。

2、请求处理器

请求处理器有setup()、handle()和finish()方法,你可以覆盖它们来定制你自己的行为。一般情况下,你只需要覆盖handle方法。BaseRequestHandler的__init__函数调用setup()方法来做初始化的工作,handle()服务于请求,finish()用于执行清理工作,如果handle或setup导致一个异常,finish不会被调用。记住,你的请求处理器会为每个请求创建一个新的实例。

request成员变量有关于流(TCP)服务的最近接受的socket;对于数据报服务,它是一个包含进入消息和监听socket的元组。client_address包含发送者的地址,server有对SocketServer的一个引用(通过这你可以访问它的成员,如server_address)。

下面的例子实现了一个EchoRequestHandler,这作为一个服务端它将客户端所发送的数据再发送回客户端:

>>> import SocketServer
>>> class EchoRequestHandler(SocketServer.BaseRequestHandler):
...    def handle(self):
...        print 'Got new connection!'
...        while 1:
...            mesg=self.request.recv(1024)
...            if not msg:
...                break
...            print 'Received:',msg
...            self.request.send(msg)
...        print 'Done with connection'
>>> server=SocketServer.ThreadingTCPServer(('127.0.0.1',12321),EchoReuestHandler)
>>> server.handle_request() #执行后将等待连接
Got new connection!
 Received: Hello!
 Received: I like Tuesdays!
Done with connection


打开另一个Python解释器作为客户端,然后执行如下代码:

>>> from socket import *
>>> s=socket(AF_INET,SOCK_STREAM)
>>> s.connect(('120.0.0.1',12321))
>>> s.send('Hello!')
6
>>> print s.recv(1024)
Hello!
>>> s.send('I like Tuesdays!')
16
>>> print s.recv(1024)
I like Tuesdays!
>>> s.close()


SocketServer模块也定义了BaseRequestHandler的两个子类:StreamRequestHandler和DatagramRequestHandler。它们覆盖了setup和finish方法并创建了两个文件对象rfile和wfile,你可以用这两个文件对象来向客户端读写数据,从而代替使用socket方法。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-370737-1-1.html 上篇帖子: 为什么俺推荐Python[1]:作为脚本语言的Python 下篇帖子: Python获取JE用户头像
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表