BaseRequestHandler 子类方法可以接触到下面三个变量:
request: 一个 socket 对象代表着客户端的请求。在 MirrorServer 例子里 socket.accept 也返回这样一个对象。
- client_address:一个包含两个成员(主机名和端口)的数组,服务端输出的任何数据都将通过它们发送。 在MirrorServer 例子中 socket.accept 返回的另一个参数就是 client_address。
- server: 对创建 request handler 对象的 SocketServer 的一个引用。
继承 StreamRequestHandler 代替继承 BaseRequestHandler ,你可以像文件操作一样对 socket 连接进行读写。 StreamRequestHandler 提供了另外两个变量:
rfile: 这个文件对应着从 socket 进来的数据。等同于调用 request.makefile(‘rb’) 。
wfile: 这个文件对应着从 socket 发送的数据。等同于调用 request.makefile(‘wb’)。
通过用将 MirrorServer 重写为一个 SocketServer 服务端(更确切,是一个 TCPServer ),你可以省略 socket 配置和拆除的大量相关代码,而专心地致力于文本的逆反工作。下面是 MirrorSocketServer.py:
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
MirrorSocketServer#!/usr/bin/python
import SocketServer
class RequestHandler(SocketServer.StreamRequestHandler):
"Handles one request to mirror some text"
def handle(self):
"""Read from StreamRequestHandler's provided rfile member,
which contains the input from the client.Mirror the text
and write it to the wfile member, which contains the output
to be sent to the client."""
l = True
while l:
l = self.rfile.readline().strip()
if l:
self.wfile.write(l[::-1] + '\n')
if __name__ = '__main__':
import sys
if len(sys.argv) < 3:
print 'Usage: %s [hostname] [port number]' % sys.argv[0]
sys.exit(1)
hostname = sys.argv[1]
port = int(sys.argv[2])
SocketServer.TCPServer((hostname,port), RequestHandler).serve_forever()
几乎所有 socket 细节的代码都没有。无论什么时候连接到这个服务端, TCPServer 类将传递正确的变量来建立一个新的 RequestHandler ,并调用 handle 方法来处理请求。
∵两个服务端在网络上所接收输入和发送的输出都是一样的,∴前面我们所写的 MirrorClient 也可以很好地与这个服务端工作。这个原则也适用于当你为精简代码面改变模块里面函数的实现,但保留了接口的一致。
Python的标准库里的服务器模块SocketServer可以很方便的开发简单的服务器程序
import SocketServer
class MyHandler(SocketServer.StreamRequestHandler):
def handle():
addr = self.request.getpeername()
print 'connection from:", addr
data = self.rfile.read(1024)
print 'data:', data
self.wfile.write('xxx')
server = SocketServer.ThreadingTCPServer((ip, host), MyHandler)
server.serve_forever()
对于UDP而言,StreamRequestHandler还可以用DatagramRequestHandler代替,ThreadingTCPServer可以用TCPServer, UDPServer代替
在 Python标准库里有如下定义:
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
pass
StreamRequestHandler是BaseRequestHandler的一个子类,我们需要创建一个自己的handler类,继承自StreamRequestHandler,
并重载StreamRequestHandler.handle()方法。
StreamRequestHandler.handle()方法的调用顺序为:
StreamRequestHandler.setup()->StreamRequestHandler.handle()->StreamRequestHandler.finish(),setup和finish调用啥也不做,可以无视
该类中,self.client_address表示客户端地址,如果是StreamRequestHandler, self.request表示socket,如果是DatagramRequestHandler,
self.request是(socket, data)的tuple。同时self.rfile, self.wfile可以用来读写
在标准库里,BaseServer通过handle_request来处理请求(serve_forever就是不停调用handle_request)。handle_request()中包含了
get_request, verify_request, process_request, finish_request。其中finish_request会调用StreamRequestHandler的handle方法。
而process_request会继承自ThreadingMixIn或者ForkingMixIn,对每个request新建线程,然后由线程调用finish_request
BaseServer的其他属性和方法请参考Python Library Reference:
BaseServer.socket: listen的socket
BaseServer.shutdown(): stop serve_forever() loop
BaseServer.allow_reuse_address
BaseServer.request_queue_size
BaseServer.handle_error: 如果RequestHandler的handle方法抛出异常,由handle_error处理