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

作者:cangmean 时间:2021-04-16 13:25:27 

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,SocketServer
0
投稿

猜你喜欢

  • 解决IE下提示“无法打开Internet站点 已终止操作”的错误

    2009-03-04 12:04:00
  • 彻底弄清楚haslayout概念

    2009-10-27 10:46:00
  • php+mysqli实现批量替换数据库表前缀的方法

    2023-11-22 10:15:55
  • python 利用百度API进行淘宝评论关键词提取

    2021-11-14 19:32:36
  • mysql慢查询的分析方法

    2010-08-03 14:51:00
  • 基于python的mysql复制工具详解

    2023-06-24 01:08:28
  • ASP程序直接连接MYSQL数据库

    2008-10-03 12:13:00
  • Oracle PL/SQL语言入门基础

    2010-07-20 13:28:00
  • Python检测数据类型的方法总结

    2022-08-29 22:07:58
  • Python如何通过变量ID得到变量的值

    2023-01-22 22:35:56
  • 使用eval()解析JSON格式字符串应注意的问题

    2008-04-16 15:46:00
  • ASP 使用jqGrid实现读写删的代码(json)

    2010-03-07 17:26:00
  • SQL Server数据库实用小技巧集合

    2008-11-25 11:35:00
  • asp如何遍历目录及目录下的文件?

    2009-11-11 17:55:00
  • python的数据与matlab互通问题:SciPy

    2022-05-16 04:53:48
  • 解决SpringBoot启动过后不能访问jsp页面的问题(超详细)

    2023-06-13 19:43:31
  • Python+ Flask实现Mock Server详情

    2021-02-11 19:56:28
  • 数据库中identity字段不必是系统产生的唯一值 性能优化方法(新招)

    2011-09-30 11:26:06
  • 解析:安装 MySQL时如何选择安装软件包

    2008-12-31 17:15:00
  • 关于Python 中的时间处理包datetime和arrow的方法详解

    2023-11-16 12:18:48
  • asp之家 网络编程 m.aspxhome.com