实例讲解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基础教程之udp端口扫描
Feb 10 Python
Python格式化压缩后的JS文件的方法
Mar 05 Python
Python实现TCP协议下的端口映射功能的脚本程序示例
Jun 14 Python
win系统下为Python3.5安装flask-mongoengine 库
Dec 20 Python
Collatz 序列、逗号代码、字符图网格实例
Jun 22 Python
基于python3实现socket文件传输和校验
Jul 28 Python
Python标准库shutil用法实例详解
Aug 13 Python
python 利用pyttsx3文字转语音过程详解
Sep 25 Python
Python数据处理篇之Sympy系列(五)---解方程
Oct 12 Python
keras模型保存为tensorflow的二进制模型方式
May 25 Python
python能否java成为主流语言吗
Jun 22 Python
Python+OpenCV检测灯光亮点的实现方法
Nov 02 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
模拟OICQ的实现思路和核心程序(二)
2006/10/09 PHP
preg_match_all使用心得分享
2014/01/31 PHP
浅谈PHP正则中的捕获组与非捕获组
2016/07/18 PHP
PHP常用函数总结(180多个)
2016/12/25 PHP
PHP 99乘法表的几种实现代码
2020/10/13 PHP
jQuery中live方法的重复绑定说明
2011/10/21 Javascript
面向对象Javascript核心支持代码分享
2012/05/23 Javascript
Javascript中的默认参数详解
2014/10/22 Javascript
Javascript实现Web颜色值转换
2015/02/05 Javascript
js限制文本框只能输入整数或者带小数点的数字
2015/04/27 Javascript
JavaScript是如何实现继承的(六种方式)
2016/03/31 Javascript
微信小程序 开发指南详解
2016/09/27 Javascript
原生JS实现匀速图片轮播动画
2016/10/18 Javascript
基于Bootstrap和jQuery构建前端分页工具实例代码
2016/11/23 Javascript
bootstrap警告框使用方法解析
2017/01/13 Javascript
PHP实现本地图片上传和验证功能
2017/02/27 Javascript
IE11下使用canvas.toDataURL报SecurityError错误的解决方法
2017/11/19 Javascript
详解如何在Vue里建立长按指令
2018/08/20 Javascript
[01:11]steam端dota2实名认证操作流程视频
2021/03/11 DOTA
[52:02]DOTA2-DPC中国联赛 正赛 Phoenix vs Dragon BO3 第二场 2月26日
2021/03/11 DOTA
Python内置数据结构与操作符的练习题集锦
2016/07/01 Python
Python实现E-Mail收集插件实例教程
2019/02/06 Python
详解Django 时间与时区设置问题
2019/07/23 Python
python的re模块使用方法详解
2019/07/26 Python
调试Django时打印SQL语句的日志代码实例
2019/09/12 Python
基于Python 中函数的 收集参数 机制
2019/12/21 Python
pandas 强制类型转换 df.astype实例
2020/04/09 Python
python中有函数重载吗
2020/05/28 Python
巴西网上药店:Drogaria Araujo
2021/01/06 全球购物
农村优秀教师事迹材料
2014/08/27 职场文书
事业单位工作人员年度考核个人总结
2015/02/12 职场文书
学生会任命书范本
2015/09/21 职场文书
申论不会写怎么办?教您掌握这6点思维和原则
2019/07/17 职场文书
七年级作文之环保作文
2019/10/17 职场文书
浅谈react useEffect闭包的坑
2021/06/08 Javascript
Win11 KB5015814遇安装失败 影响开始菜单性能解决方法
2022/07/15 数码科技