实例讲解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()
猜你喜欢
- 本篇,我们学习PyQt5界面中拖放(Drag 和Drop)控件。拖放动作在GUI中,拖放指的是点击一个对象,并将其拖动到另一个对象上的动作。
- 我在程序中加入了分数显示,三种特殊食物,将贪吃蛇的游戏逻辑写到了SnakeGame的类中,而不是在Snake类中。特殊食物:1.绿色:普通,
- 代码如下:using System; using System.Data; using System.Configuration; usin
- 一:操作session1:session配置Session 的配置文件存储在config/session.php中,配置参数有:(1):配置
- 当我们建好数据库及表后,首先想到的就是向数据库的表中输入数据.下面我们就来探讨一下如何向数据库增加数据:1.常用的方法是insert语句in
- 1.func Copy(dst Writer, src Reader) (written int64, err error)这个函数是从一个
- 使用 Microsoft® SQL Server™ 2000,可以选择在一台计算机上安装 SQL Ser
- 揭秘一个普通的输入框背后惊人的秘密。某月某日,某项目某页面,需要一个价格区间筛选功能,需求合理,所以设计做上去。这是一个无比普通的输入框。在
- 代码如下:--相信大家肯定经常会把数据导入到数据库中,但是可能会有些记录行的所有列的数据是null,这为null的数据是我们不需要 --现在
- 一、背景:nginx 的log 不会自动按天备份,而且记录时间格式不统一,此程序专门解决这两个问题;二、windows 部署方式1.在 ng
- 项目开始时是一个关键时刻,选择会对项目产生长期的影响。有很多关于如何开始使用Django框架的教程,但很少讨论如何专业地使用Django,或
- python发送icmp echo requesy请求import socketimport structdef checksum(sour
- 1.问:在DW中如何设置页面边距为0?答:在DW中似乎没有直接设置的方法,你只有在Html文档中插入以
- 问题:有一个列表,每一个条目都是这篇文章的部分内容,类似这样:<div class="list">
- 国庆假期快到了,想查查还有几天几小时到假期,这对程序员
- ------谁正在访问数据库?Select c.sid, c.serial#,c.username,a.object_id,b.
- txt文件转换为XML很多目标检测的模型都是默认需要VOC的文件输入格式手上数据label是txt文件。为了避免不必要的bug,还是选择转换
- Mac系统上虽然自带PHP和Apache,但是有时不是我们想要的版本呢。今天我们就在macOS Sierra(10.12.1)上安装比较新的
- 为什么是三谈为什么是三谈呢?一是因为这真的是一个被说烂的话题,二是因为太师傅在n年前就写过这篇再谈iframe自适应高度。之所以再提该问题,
- 一、使用 reflect.Type 创建实例在通过 reflect.TypeOf 函数获取到变量的反射类型对象之后,可以通过反射类型对象 r