Python使用SocketServer模块编写基本服务器程序的教程


Posted in Python onJuly 12, 2016

SocketServer简化了网络服务器的编写。它有4个类:TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer。这4个类是同步进行处理的,另外通过ForkingMixIn和ThreadingMixIn类来支持异步。

创建服务器的步骤。首先,你必须创建一个请求处理类,它是BaseRequestHandler的子类并重载其handle()方法。其次,你必须实例化一个服务器类,传入服务器的地址和请求处理程序类。最后,调用handle_request()(一般是调用其他事件循环或者使用select())或serve_forever()。

集成ThreadingMixIn类时需要处理异常关闭。daemon_threads指示服务器是否要等待线程终止,要是线程互相独立,必须要设置为True,默认是False。

无论用什么网络协议,服务器类有相同的外部方法和属性。

在Python3中,本模块为socketserver模块。在Python 2中,本模块为SocketServer模块。所以在用import导入时,要分情况导入,否则会报错。导入的代码如下:

try:
  import socketserver   #Python 3
except ImportError:
  import SocketServer   #Python 2

SocketSerror模块包括许多可以简化TCP、UDP、UNIX域套接字  服务器实现的类。

一、处理程序
要使用本模块,必须定义一个继承于基类BaseRequestHandler的处理程序类。BaseRequestHandler类的实例h可以实现以下方法:
1、h.handle()  调用该方法执行实际的请求操作。调用该函数可以不带任何参数,但是几个实例变量包含有用的值。h.request包含请求,h.client_address包含客户端地址,h.server包含调用处理程序的实例。对于TCP之类的数据流服务,h.request属性是套接字对象。对于数据报服务,它是包含收到数据的字节字符串。
2、h.setup()   该方法在handle()之前调用。默认情况下,它不执行任何操作。如果希望服务器实现更多连接设置(如建立SSL连接),可以在这里实现。
3、h.finish()   调用本方法可以在执行完handle()之后执行清除操作。默认情况下,它不执行任何操作。如果setup()和handle()方法都不生成异常,则无需调用该方法。
如果知道应用程序只能操纵面向数据流的连接(如TCP),那么应从StreamRequestHandler继承,而不是BaseRequestHandler。StreamRequestHandler类设置了两个属性,h.wfile是将数据写入客户端的类文件对象,h.rfile是从客户端读取数据的类文件对象。
如果要编写针对数据包操作的处理程序并将响应持续返回发送方,那么它应当从DatagramRequestHandler继承。它提供的类接口与StramRequestHandler相同。

二、服务器
要使用处理程序,必须将其插入到服务器对象。定义了四个基本的服务器类。
(1)TCPServer(address,handler)   支持使用IPv4的TCP协议的服务器,address是一个(host,port)元组。Handler是BaseRequestHandler或StreamRequestHandler类的子类的实例。
(2)UDPServer(address,handler)   支持使用IPv4的UDP协议的服务器,address和handler与TCPServer中类似。
(3)UnixStreamServer(address,handler)   使用UNIX域套接字实现面向数据流协议的服务器,继承自TCPServer。
(4)UnixDatagramServer(address,handler)  使用UNIX域套接字实现数据报协议的服务器,继承自UDPServer。
所有四个服务器类的实例都有以下方法和变量:
1、s.socket   用于传入请求的套接字对象。
2、s.sever_address  监听服务器的地址。如元组("127.0.0.1",80)
3、s.RequestHandlerClass   传递给服务器构造函数并由用户提供的请求处理程序类。
4、s.serve_forever()  处理无限的请求
5、s.shutdown()   停止serve_forever()循环
6、s.fileno()   返回服务器套接字的整数文件描述符。该方法可以有效地通过轮询操作(如select()函数)使用服务器实例。

三、定义自定义服务器
服务器往往需要特殊的配置来处理不同的网络地址族、超时期、并发和其他功能,可以通过继承上面四个基本服务器类来自行定义。
可以通过混合类获得更多服务器功能,这也是通过进程或线程分支添加并发行的方法。为了实现并发性,定义了以下类:
(1)ForkingMixIn         将UNIX进程分支添加到服务器的混合方法,使用该方法可以让服务器服务多个客户。
(2)ThreadingMixIn    修改服务器的混合类,可以使用线程服务多个客户端。
要向服务器添加这些功能,可以使用多重继承,其中首先列出混了类。
由于并发服务器很常用,为了定义它,SocketServer预定义了以下服务器类:
(1)ForkingUDPServer(address,handler)  
(2)ForkingTCPServer(address,handler)
(3)ThreadingUDPServer(address,handler)
(4)ThreadingTCPServer(address,handler)
上面有点乱,现总结以下:
SocketServer模块中的类主要有以下几个:
1、BaseServer    包含服务器的核心功能与混合类(mix-in)的钩子功能。这个类主要用于派生,不要直接生成这个类的类对象,可以考虑使用TCPServer和UDPServer类。
2、TCPServer    基本的网络同步TCP服务器
3、UDPServer    基本的网络同步UDP服务器
4、ForkingMixIn   实现了核心的进程化功能,用于与服务器类进行混合(mix-in),以提供一些异步特性。不要直接生成这个类的对象。
5、ThreadingMixIn   实现了核心的线程化功能,用于与服务器类进行混合(mix-in),以提供一些异步特性。不要直接生成这个类的对象。
6、ForkingTCPServer     ForkingMixIn与TCPServer的组合
7、ForkingUDPServer    ForkingMixIn与UDPServer的组合
8、BaseRequestHandler
9、StreamRequestHandler    TCP请求处理类的一个实现
10、DataStreamRequestHandler   UDP请求处理类的一个实现
现在繁杂的事务都已经封装到类中了,直接使用类即可。

四、实例
1.使用SocketServer模块编写的TCP服务器端代码:

#! /usr/bin/env python
#coding=utf-8
"""使用SocketServer来实现简单的TCP服务器"""
from SocketServer import (TCPServer,StreamRequestHandler as SRH)
from time import ctime
class MyRequestHandler(SRH):
  def handle(self):
    print "connected from ",self.client_address
    self.wfile.write("[%s] %s" %(ctime(),self.rfile.readline()))
tcpSer=TCPServer(("",10001),MyRequestHandler)
print "waiting for connection"
tcpSer.serve_forever()
相应的TCP客户端代码:
#! /usr/bin/env python
#coding=utf-8
from socket import *
BUFSIZE=1024
#每次都要创建新的连接
while True:
  tcpClient=socket(AF_INET,SOCK_STREAM)
  tcpClient.connect(("localhost",10001))
  data=raw_input(">")
  if not data:
    break
  tcpClient.send("%s\r\n" %data)
  data1=tcpClient.recv(BUFSIZE)
  if not data1:
    break
  print data1.strip()
  tcpClient.close()

2.异步服务器的实现

ThreadingMixIn的例子:

import socketimport threadingimport SocketServerclass ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):

  def handle(self):
    data = self.request.recv(1024)
    cur_thread = threading.current_thread()
    response = "{}: {}".format(cur_thread.name, data)
    self.request.sendall(response)class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
  passdef client(ip, port, message):
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  sock.connect((ip, port))
  try:
    sock.sendall(message)
    response = sock.recv(1024)
    print "Received: {}".format(response)
  finally:
    sock.close()if __name__ == "__main__":
  # Port 0 means to select an arbitrary unused port
  HOST, PORT = "localhost", 0

  server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
  ip, port = server.server_address  # Start a thread with the server -- that thread will then start one
  # more thread for each request
  server_thread = threading.Thread(target=server.serve_forever)
  # Exit the server thread when the main thread terminates
  server_thread.daemon = True
  server_thread.start()
  print "Server loop running in thread:", server_thread.name

  client(ip, port, "Hello World 1")
  client(ip, port, "Hello World 2")
  client(ip, port, "Hello World 3")

  server.shutdown()

执行结果:

$ python ThreadedTCPServer.py
Server loop running in thread: Thread-1
Received: Thread-2: Hello World 1
Received: Thread-3: Hello World 2
Received: Thread-4: Hello World 3
Python 相关文章推荐
python实现通过shelve修改对象实例
Sep 26 Python
python实现class对象转换成json/字典的方法
Mar 11 Python
python虚拟环境virualenv的安装与使用
Dec 18 Python
Python爬取网页中的图片(搜狗图片)详解
Mar 23 Python
python通过伪装头部数据抵抗反爬虫的实例
May 07 Python
python requests指定出口ip的例子
Jul 25 Python
在macOS上搭建python环境的实现方法
Aug 13 Python
Django查询优化及ajax编码格式原理解析
Mar 25 Python
Python计算指定日期是今年的第几天(三种方法)
Mar 26 Python
Python+Selenium随机生成手机验证码并检查页面上是否弹出重复手机号码提示框
Sep 21 Python
pytorch 计算Parameter和FLOP的操作
Mar 04 Python
python基础之//、/与%的区别详解
Jun 10 Python
使用Python的Flask框架表单插件Flask-WTF实现Web登录验证
Jul 12 #Python
Python的Flask框架标配模板引擎Jinja2的使用教程
Jul 12 #Python
深度定制Python的Flask框架开发环境的一些技巧总结
Jul 12 #Python
Python的面向对象编程方式学习笔记
Jul 12 #Python
Python使用cookielib模块操作cookie的实例教程
Jul 12 #Python
Python网络编程中urllib2模块的用法总结
Jul 12 #Python
Python中内置的日志模块logging用法详解
Jul 12 #Python
You might like
JavaScript中使用replace结合正则实现replaceAll的效果
2010/06/04 Javascript
jQuery UI Dialog控件中的表单无法正常提交的解决方法
2010/12/19 Javascript
dtree 网页树状菜单及传递对象集合到js内,动态生成节点
2012/04/14 Javascript
使用JQ来编写最基本的淡入淡出效果附演示动画
2014/10/31 Javascript
JS失效 提示HTML1114: (UNICODE 字节顺序标记)的代码页 utf-8 覆盖(META 标记)的冲突的代码页 utf-8
2017/06/23 Javascript
bootstrap精简教程_动力节点Java学院整理
2017/07/14 Javascript
webstorm和.vue中es6语法报错的解决方法
2018/05/08 Javascript
从0到1构建vueSSR项目之node以及vue-cli3的配置
2019/03/07 Javascript
仿ElementUI实现一个Form表单的实现代码
2019/04/23 Javascript
深入浅出vue图片路径的实现
2019/09/04 Javascript
微信小程序实现列表滚动头部吸顶的示例代码
2020/07/12 Javascript
[49:40]2018DOTA2亚洲邀请赛小组赛 A组加赛 TNC vs Newbee
2018/04/03 DOTA
在Python的Flask中使用WTForms表单框架的基础教程
2016/06/07 Python
读写json中文ASCII乱码问题的解决方法
2016/11/05 Python
Python常见异常分类与处理方法
2017/06/04 Python
Python使用django框架实现多人在线匿名聊天的小程序
2017/11/29 Python
Python提取特定时间段内数据的方法实例
2019/04/01 Python
基于Python fminunc 的替代方法
2020/02/29 Python
python基于openpyxl生成excel文件
2020/12/23 Python
一款基于css3的列表toggle特效实例教程
2015/01/04 HTML / CSS
Rockport乐步美国官网:风靡美国的白宫鞋
2016/11/24 全球购物
中东地区为妈妈们提供一切的头号购物目的地:Sprii
2018/05/06 全球购物
纽约州一群才华横溢的金匠制作而成:Hearth Jewelry
2019/03/22 全球购物
巴西香水和化妆品购物网站:The Beauty Box
2019/09/03 全球购物
德国便宜的宠物店:Brekz.de
2020/10/23 全球购物
亚洲领先的设计购物网站:Pinkoi
2020/11/26 全球购物
武汉东之林科技有限公司机试
2013/09/17 面试题
办公设备采购方案
2014/03/16 职场文书
七夕相亲活动策划方案
2014/08/31 职场文书
青春飞扬演讲稿
2014/09/11 职场文书
2014年党员自我评议总结
2014/09/23 职场文书
公路施工安全责任书
2015/05/08 职场文书
资深HR教你写好简历中的自我评价
2019/05/07 职场文书
阿里云服务器部署mongodb的详细过程
2021/09/04 MongoDB
python编程简单几行代码实现视频转换Gif示例
2021/10/05 Python
MySQL中的 inner join 和 left join的区别解析(小结果集驱动大结果集)
2023/05/08 MySQL