实例讲解Python中SocketServer模块处理网络请求的用法


Posted in Python onJune 28, 2016

SocketServer创建一个网络服务框架。它定义了类来处理TCP,UDP, UNIX streams 和UNIX datagrams上的同步网络请求。

一、Server Types

有五个不同的服务器类在SocketServer中。

1.BaseServer定义了API, 而且他不是用来实例化和直接使用的。
2.TCPServer用作TCP/IP的socket通讯。
3.UDPServer使用datagram sockets。
4.UnixStreamServer和UnixDatagramServer使用Unix-domain sockets而且智能在unix平台上使用。

二、Server Objects

构建一个服务器, 通过它来监听请求的地址和请求的处理类(not instance)。

1.class SocketServer.BaseServer
这是模块中所有服务器对象的超类,它定义了接口,实现大多数都在子类中完成。

2.BaseServer.fileno

返回一个整数文件描述符来表示哪个服务器正在监听。这个函数最常见的传递给select.select(),允许监控多个相同处理过程的服务。

3.BaseServer.handle_request

处理单一的请求,这个函数会顺序调用接下来的方法。get_request(),verify_request和proccess_request。
用户提供handle()方法抛出一个异常,那么handle_error()方法会被调用。
self.timeout的时间内没有收到请求,handle_timeout()和handle_request()将返回。

4.BaseServer.serve_forever

BaseServer.serve_forever(poll_interval=0.5),处理请求一直到明确的shutdown()请求。轮训每隔poll_interval时间内关闭。忽略self.timeout,如果需要使用定时任务,需要使用其他线程。

5.BaseServer.shutdown

告诉serve_forever()循环停止。

6.BaseServer.RequestHandlerClass

用户请求处理程序类,为每个请求创建这个类的一个实例。

三、Implementing a Server

如果你创建一个服务器,它通常可以重复使用现有的类和简单的提供一个自定义请求处理的类。如果不符合需求,有几种BaseServer方法覆盖一个子类。

1.verify_request(reqeust, client_address): 必须返回一个布尔值,如果返回True,请求将被处理,如果返回False,请求将被拒绝。这个函数可以覆盖来实现访问控制服务。
2.process_request(request, client_address): 调用finish_request来创建一个RequestHandlerClass()的实例,如果需要该函数可以创建一个新的进程或协程来处理请求。
3.finish_request(request, client_address): 创建一个请求处理实例。调用handle()来处理请求。

四、Request Handlers

请求处理程序做的大部分工作接收传入的请求,并决定采取何种行动。处理程序负责实现“协议”上的套接字层(例如,HTTP或xml - rpc)。从传入的请求处理程序读取请求数据通道,流程,和写一个响应。有三个方法可以重写。

1.setup(): 准备请求的请求处理程序, 就是初始化运行在handle之前。
2.handle(): 做真正的请求工作。解析传入的请求,处理数据和返回响应。
3.finish(): 清理任意时间创建的setup()。

五、例子

下面例子展示了tcp, udp和异步

1.TCPServer 例子

import SocketServer


class MyHandler(SocketServer.BaseRequestHandler):
  
  def handle(self):
    self.data = self.request.recv(1024).strip()
    print '{} wrote:'.format(self.client_address[0])
    print self.data
    self.request.sendall(self.data.upper())


if __name__ == '__main__':
  HOST, PORT = 'localhost', 9999
  server = SocketServer.TCPServer((HOST, PORT), MyHandler)
  server.serve_forever()

2.UDPServr 例子

import SocketServer


class MyHandler(SocketServer.BaseRequestHandler):

  def handle(self):
    data = self.request[0].strip()
    socket = self.request[1]
    print '{} wrote:'.format(self.client_address[0])
    print data
    socket.sendto(data.upper(), self.client_address)


if __name__ == '__main__':
  HOST, PORT = 'localhost', 9999
  server = SocketServer.UDPServer((HOST, PORT), MyHandler)
  server.serve_forever()

3.异步例子

可以通过ThreadingMixIn和ForkingMixIn类来构造异步处理程序。

import socket
import threading
import SocketServer


class MyHandler(SocketServer.BaseRequestHandler):

  def handle(self):
    data = self.request.recv(1024)
    curr_thread = threading.current_thread()
    response = '{}: {}'.format(curr_thread.name, data)
    self.request.sendall(response)


class Server(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
  pass


def 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__':
  HOST, PORT = 'localhost', 0

  server = Server((HOST, PORT), MyHandler)
  ip, port = server.server_address

  serer_thread = threading.Thread(target=server.serve_forever)
  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()
  server.server_close()

4.SocketServer 实现客户端与服务器间非阻塞通信
(1)创建SocketServerTCP服务端

#创建SocketServerTCP服务器: 
import SocketServer 
from SocketServer import StreamRequestHandler as SRH 
from time import ctime 
 
host = 'xxx.xxx.xxx.xxx' 
port = 9999 
addr = (host,port) 
 
class Servers(SRH): 
  def handle(self): 
    print 'got connection from ',self.client_address 
    self.wfile.write('connection %s:%s at %s succeed!' % (host,port,ctime())) 
    while True: 
      data = self.request.recv(1024) 
      if not data:  
        break 
      print data 
      print "RECV from ", self.client_address[0] 
      self.request.send(data) 
print 'server is running....' 
server = SocketServer.ThreadingTCPServer(addr,Servers) 
server.serve_forever()

(2)创建SocketServerTCP客户端

from socket import * 
 
host = 'xxx.xxx.xxx.xxx' 
port = 9999 
bufsize = 1024 
addr = (host,port) 
client = socket(AF_INET,SOCK_STREAM) 
client.connect(addr) 
while True: 
  data = raw_input() 
  if not data or data=='exit': 
    break 
  client.send('%s\r\n' % data) 
  data = client.recv(bufsize) 
  if not data: 
    break 
  print data.strip() 
client.close()
Python 相关文章推荐
Python使用Mechanize模块编写爬虫的要点解析
Mar 31 Python
Python编程之字符串模板(Template)用法实例分析
Jul 22 Python
Python通过matplotlib绘制动画简单实例
Dec 13 Python
python+pandas生成指定日期和重采样的方法
Apr 11 Python
对numpy中轴与维度的理解
Apr 18 Python
Python基于多线程实现ping扫描功能示例
Jul 23 Python
Python命名空间的本质和加载顺序
Dec 17 Python
Pycharm 设置默认头的图文教程
Jan 17 Python
python matplotlib模块基本图形绘制方法小结【直线,曲线,直方图,饼图等】
Apr 26 Python
django序列化时使用外键的真实值操作
Jul 15 Python
python利用faker库批量生成测试数据
Oct 15 Python
Python一些基本的图像操作和处理总结
Jun 23 Python
Python中asyncore异步模块的用法及实现httpclient的实例
Jun 28 #Python
python 字典(dict)按键和值排序
Jun 28 #Python
简单谈谈python的反射机制
Jun 28 #Python
Python实现带百分比的进度条
Jun 28 #Python
Python中的字符串替换操作示例
Jun 27 #Python
Python的string模块中的Template类字符串模板用法
Jun 27 #Python
Python的Flask框架及Nginx实现静态文件访问限制功能
Jun 27 #Python
You might like
PHP中其实也可以用方法链
2011/11/10 PHP
php.ini 配置文件的深入解析
2013/06/17 PHP
WordPres对前端页面调试时的两个PHP函数使用小技巧
2015/12/22 PHP
基于thinkPHP3.2实现微信接入及查询token值的方法
2017/04/18 PHP
laravel model模型定义实现开启自动管理时间created_at,updated_at
2019/10/17 PHP
工作需要写的一个js拖拽组件
2011/07/28 Javascript
jquery、js操作checkbox全选反选
2014/03/12 Javascript
在JS数组特定索引处指定位置插入元素
2014/07/27 Javascript
javascript使用appendChild追加节点实例
2015/01/12 Javascript
微信企业号开发之微信考勤百度地图定位
2015/09/11 Javascript
原生JS实现旋转木马式图片轮播插件
2016/04/25 Javascript
jQuery+ajax简单实现文件上传的方法
2016/06/03 Javascript
深入浅出ES6之let和const命令
2016/08/25 Javascript
微信公众平台开发教程(四) 实例入门:机器人回复(附源码)
2016/12/02 Javascript
jquery广告无缝轮播实例
2017/01/05 Javascript
原生js实现瀑布流布局
2017/03/08 Javascript
基于JavaScript实现移动端无限加载分页
2017/03/27 Javascript
微信小程序访问豆瓣电影api的实现方法
2019/03/31 Javascript
使用jquery-easyui的布局layout写后台管理页面的代码详解
2019/06/19 jQuery
Vue基于iview实现登录密码的显示与隐藏功能
2020/03/06 Javascript
vue组件暴露和.js文件暴露接口操作
2020/08/11 Javascript
用Python实现QQ游戏大家来找茬辅助工具
2014/09/14 Python
Mac中升级Python2.7到Python3.5步骤详解
2017/04/27 Python
使用Python操作FTP实现上传和下载的方法
2019/04/01 Python
python如何实现数据的线性拟合
2019/07/19 Python
python机器学习实现决策树
2019/11/11 Python
基于python实现蓝牙通信代码实例
2019/11/19 Python
CSS3条纹背景制作的实战攻略
2016/05/31 HTML / CSS
用React加CSS3实现微信拆红包动画效果
2017/03/13 HTML / CSS
用HTML5制作视频拼图的教程
2015/05/13 HTML / CSS
Giglio美国站:意大利奢侈品购物网
2018/02/10 全球购物
波兰运动鞋网上商店:e-Sporting
2018/02/16 全球购物
高中生的自我鉴定范文
2014/01/24 职场文书
运动会广播稿20字
2014/02/18 职场文书
租车协议书范本
2014/04/22 职场文书
2014年新生军训方案
2014/05/01 职场文书