python socketserver

来源:互联网 发布:东莞小姐的体验知乎 编辑:程序博客网 时间:2024/06/11 17:35

原文:http://blog.csdn.net/fxjtoday/article/details/6307285

Python网络编程之SocketServer

      尽管 Sockets 非常的有用,但是 Python 并不满足于仅提供一个在大多数操作系统和大多数编程语言都提供的基于 C 语言似的 Socket 接口。 Python 走得更远,提供了 SocketServer——一个提供让你可以用简单的代码编写基于 socket 的复杂服务端的类集合的模块。

      建立一个 SocketServer 所要做的大部分工作是定义一个请求处理( request handler )类。它是 SocktServer 模块里 BaseRequestHandler 类的子类,并且每一个 request handler 对象在客户端连接到服务端时处理着一个客户端的请求。这是在请求处理的 handle 方法里实现的。当然请求处理也可以通过对 setup 和 finish 方法的重载来定义每个请求设置和请求拆下时的代码。

      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:

import SocketServerclass 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 textand write it to the wfile member, which contains the outputto be sent to the client."""l = Truewhile l:l = self.rfile.readline().strip()if l:self.wfile.write(l[::-1] + '\n')if __name__ = '__main__':import sysif 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 也可以很好地与这个服务端工作。这个原则也适用于当你为精简代码面改变模块里面函数的实现,但保留了接口的一致