《Python Network Programming Cookbook》读书笔记2---复用socket I/O 实现更好的性能

  第二章主要在上一章的基础上介绍了以下内容:

    1. ForkingMixIn

    2. ThreadingMixIn

    3. select.select

    4. select.epoll

    5. Diesel库

ForkingMixIn 和 ThreadingMixIn属于socketserver(python2是SocketServer)模块,该模块能够简化编写web服务器的工作。其包含四种基本的服务器class:

  TCPServer 使用TCP协议,在服务器和客户端之间建立持续的连续,安全;

  UDPServer 使用UDP协议,采用数据包的方法在服务器和客户端之间传递数据,有丢失包的可能,但是传输速度很快;

  UnixStreamServer和UnixDatagramServer 比较少使用, 分别与TCPServer、UDPServer相似,但是基于Unix上定义的套接字,在其他平台上不能使用。

图1. Servers的继承关系

以上四种类都是同步的,即下一个请求开始前,上一个请求必须完成。显然,他们并不适用于当请求需要较长处理时间的情况。为每个请求创建单独的进程或线程的方式可以解决这个问题,即实现服务器和客户端的异步通信,为此socketserver模块添加了ForkingMixIn和ThreadingMixIn两个类。

  为了创建一个服务,首先通过继承BaseRequestHandler类并重写其handler()方法得到一个句柄类,它将用来处理到达服务器的请求;

class ForkingServerRequestHandler(SocketServer.BaseRequestHandler):

然后以服务器地址和上一步得到的句柄实例化前面继承自ForkingMixIn/ThreadingMixIn和TCPServer/UDPServer/UnixStreamServer/UnixDatagramServer的server,

class ForkingServer(SocketServer.ForkingMixIn, SocketServer.TCPServer,):
    pass

server = ForkingServer((SERVER_HOST, SERVER_PORT), ForkingServerRequestHandler)

注意:ForkingMixIn必须写在TCPServer前面,因为它重载了TCPServer类的方法。

最后,调用handler_request()或者server_forever()方法来开始处理请求。

server_thread = threading.Thread(target=server.serve_forever)

  值得注意的是,如果server类继承自ThreadingMixIn,则需要明确指定遇到异常停止时的处理方法,ThreadingMixIn类定义了daemon_threads方法,其指定了服务器是否需要等待直到所有线程终止,默认为False。

server_thread.setDaemon(True)

下面是一个简单的例子:

import os
   import socket
   import threading
   import SocketServer
   SERVER_HOST = ‘localhost‘
   SERVER_PORT = 0 # tells the kernel to pick up a port dynamically
   BUF_SIZE = 1024
   ECHO_MSG = ‘Hello echo server!‘
   class ForkedClient():
       """ A client to test forking server"""
       def __init__(self, ip, port):
           # Create a socket
           self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
           # Connect to the server
            self.sock.connect((ip, port))
       def run(self):
           """ Client playing with the server"""
           # Send the data to server
           current_process_id = os.getpid()
           print ‘PID %s Sending echo message to the server : "%s"‘ %
   (current_process_id, ECHO_MSG)
           sent_data_length = self.sock.send(ECHO_MSG)
           print "Sent: %d characters, so far..." %sent_data_length
           # Display server response
           response = self.sock.recv(BUF_SIZE)
           print "PID %s received: %s" % (current_process_id,
   response[5:])
       def shutdown(self):
           """ Cleanup the client socket """
           self.sock.close()
   class ForkingServerRequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
           # Send the echo back to the client
           data = self.request.recv(BUF_SIZE)
           current_process_id = os.getpid()
           response = ‘%s: %s‘ % (current_process_id, data)
           print "Server sending response [current_process_id: data] =
   [%s]" %response
           self.request.send(response)
return
   class ForkingServer(SocketServer.ForkingMixIn,
                       SocketServer.TCPServer,
                       ):
       """Nothing to add here, inherited everything necessary from
   parents"""
       pass
   def main():
       # Launch the server
       server = ForkingServer((SERVER_HOST, SERVER_PORT),
   ForkingServerRequestHandler)
       ip, port = server.server_address # Retrieve the port number
       server_thread = threading.Thread(target=server.serve_forever)
       server_thread.setDaemon(True) # don‘t hang on exit
       server_thread.start()
       print ‘Server loop running PID: %s‘ %os.getpid()
       # Launch the client(s)
       client1 =  ForkedClient(ip, port)
       client1.run()
       client2 =  ForkedClient(ip, port)
       client2.run()
       # Clean them up
       server.shutdown()
       client1.shutdown()
       client2.shutdown()
       server.socket.close()
   if __name__ == ‘__main__‘:
       main()

  

时间: 2024-07-29 15:02:08

《Python Network Programming Cookbook》读书笔记2---复用socket I/O 实现更好的性能的相关文章

《Python Network Programming Cookbook》读书笔记0---前言

最近打算学习python网络开发方面的内容,于是网上找来一本<Python Network Programming Cookbook>电子书做教材,顺便边学边将学到的这容通过博客的形式总结起来与大家分享. 这本书不长,英文原版也只有234页,但涉及面很广,TCP/UDP HTTP/HTTPS FTP SMTP POP3 IMAP CGI均有介绍,依照章节,博文会按如下9个部分介绍: 套接字, IPv4,  简单的Client/Server程序 更好的性能:复用套接字 I/O IPv6, UNI

《Python Network Programming Cookbook》读书笔记1---套接字, IPv4, 简单的Client/Server程序

这一部分主要介绍python中socket模块的相关内容,socket即套接字. socket是使用TCP/IP协议的应用程序通常采用的应用编程接口,它位于运输层和应用层之间,起源于UNIX,由于遵从UNIX“一切皆文件的”思想故socket可看作一种特殊的文件,对其的操作基本可以视为读写I/O.打开.关闭.关于套接字的基本概念@吴秦的Linux Socket编程(不限Linux)写的很详细,大家可以参考. 在下面列出的各个部分中我将先贴出代码,然后对其进行解释. 通过python3获得本机名和

MySQL Cookbook读书笔记第三章

1,查询指定列/从指定列中查询 若需要指定每一列在查询结果中出现的先后顺序,可以在select语句中指定(dstuser在dsthost之后): 查询显示用户所关注的列: 2,指定查询行 使用where关键字可以查询符合条件限制的数据例如:查找srchost为venus或者srchost以s开头的行记录: 使用操作符like进行模式匹配,其中%表示通配符,代表一个差多为任意值的字符串. where使用操作符and可以查询多个条件: 条件并集: 3,格式化显示查询结果 当查询语句中没有重命名列名,

MySQL cookbook读书笔记第六章

1,修改MySQL中的日期的格式 在显示一个日期值时,如果没有特别指定,MySQL按照ISO格式显示日期即(CCYY-MM0DD).如果不希望按照MySQL的默认格式输出时间和日期值,可以使用date_format()或者time_format()函数按照用户期望的格式重写日期或者时间值 date_format(),time_format()和str_to_date()三个函数都接受格式化串作为参数: 2,设置客户端时区 如果客户端和服务器处在不同的时区,那么客户端在服务器上保存timestam

MySQL Cookbook读书笔记第5章

1,字符串属性 查看系统拥有那些字符集: 若需要来自多种语言存放到同一列中,会考虑Unicode字符集(utf8或ucs2),只有它能表示多语言的字符 有些字符集支持多字节,有些只包含单字节,判断是否支持多字节的方法是对比Length()h和char_length函数的返回值来判定字符串中是否有多字节.例如使用ucs2的字节长度为6,字符数目为3. 另外虽然Unicode字符集utf8包含多字节字符,但是一个具体的字符串有可能只包含单字节字 非二进制字符串另一特征是collation,决定字符集

分享:Foundations of Python Network Programming(3rd) 英文版pdf 下载

Foundations of Python Network Programming Third Edition 下载http://www.amazon.com/Foundations-Python-Network-Programming-Brandon/dp/1430258543这本书是2014年底出版的,基于最新的 python3.4 版本.配书源码链接https://github.com/brandon-rhodes/fopnp 目录 Chapter 1: Introduction to C

《Python学习手册》读书笔记【转载】

转载:http://www.cnblogs.com/wuyuegb2312/archive/2013/02/26/2910908.html 之前为了编写一个svm分词的程序而简单学了下Python,觉得Python很好用,想深入并系统学习一下,了解一些机制,因此开始阅读<Python学习手册(第三版)>.如果只是想快速入门,我在这里推荐了几篇文章,有其他语言编程经验的人简单看一看就可以很快地开始编写Python程序了. 黑体表示章节, 下划线表示可以直接在原文对应位置查到的专有技术名词. 原书

C++ Programming language读书笔记

http://blog.163.com/leonary_dy/blog/static/405528602009122103416862/ 虽然很多人一再强调语言细节不重要,可我还是要花时间重读经典.上次我认认真真读这本书还要追溯到两年前,现在我对C++的理解更深了一层,可以从书中读到一些两年前无法领悟的东西. 声明:本笔记只记录我以前不了解的部分,请初学者不要作为书籍摘要 我看的是TCPL电子版第三版,June 1997第一次印刷.这是网上最常见的版本,前两页书皮虽然写着special版,其实后

Go Programming Blueprints 读书笔记(谈到了nsq/mgo处理数据持久化,但是业务逻辑不够复杂)

Go Programming Blueprints http.Handle("/", &templateHandler{filename: "chat.html"}); http.Handle静态方法? 带参数的函数对象参数? 就是个普通的struct--为何不需要new? go get github.com/gorilla/websocket(方便的包依赖管理!) Go语句不需要:标记结束 TDD: 在没有定义type struct之前假设已经存在? 控制