在Python中使用异步Socket编程性能测试


Posted in Python onJune 25, 2014

OK,首先写一个python socket的server段,对开放三个端口:10000,10001,10002.krondo的例子中是每个server绑定一个端口,测试的时候需要分别开3个shell,分别运行.这太麻烦了,就分别用三个Thread来运行这些services.

import optparse 
import os 
import socket 
import time 
from threading import Thread 
import StringIO 
  
txt = '''1111 
2222 
3333 
4444 
''' 
  
  def server(listen_socket): 
  while True: 
    buf = StringIO.StringIO(txt) 
    sock, addr = listen_socket.accept() 
    print 'Somebody at %s wants poetry!' % (addr,) 
    while True: 
        try: 
          line = buf.readline().strip() 
          if not line: 
            sock.close() 
            break 
          sock.sendall(line) # this is a blocking call 
          print 'send bytes to client:%s' % line 
          #sock.close() 
        except socket.error: 
          sock.close() 
          break 
        time.sleep(1) #server和client连接后,server会故意每发送一个单词后等待一秒钟后再发送另一个单词 
  
  def main(): 
  ports = [10000, 10001, 10002] 
  for port in ports: 
    listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    addres = (str('127.0.0.1'), port) 
    listen_socket.bind(addres) 
    listen_socket.listen(5) 
    print "start listen at:%s" % (port,) 
    worker = Thread(target = server, args = [listen_socket]) 
    worker.setDaemon(True) 
    worker.start() 
  
  if __name__ == '__main__': 
  main() 
  while True: 
    time.sleep(0.1) #如果不sleep的话,CPU会被Python完全占用了 
    pass

下面是一个client,没有才用异步网络,连接这个三个端口的server:

import socket 
  
  
if __name__ == '__main__': 
  ports = [10000, 10001, 10002] 
  for port in ports: 
    address = (str('127.0.0.1'), port) 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.connect(address) 
    poem = '' 
    while True: 
      data = sock.recv(4) 
      if not data: 
        sock.close() 
        break 
      poem += data 
    print poem

下面用异步的client来读取,代码如下:

import datetime, errno, optparse, select, socket 
  
def connect(port): 
  """Connect to the given server and return a non-blocking socket.""" 
  address = (str('127.0.0.1'), port) 
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
  sock.connect(address) 
  sock.setblocking(0) 
  return sock 
  
def format_address(address): 
  host, port = address 
  return '%s:%s' % (host or '127.0.0.1', port) 
  
if __name__ == '__main__': 
  ports = [10000, 10001, 10002] 
  start = datetime.datetime.now() 
  
  sockets = map(connect, ports) 
  poems = dict.fromkeys(sockets, '') # socket -> accumulated poem  
  
  # socket -> task numbers 
  sock2task = dict([(s, i + 1) for i, s in enumerate(sockets)]) 
  sockets = list(sockets) # make a copy 
  
  while sockets: 
    #运用select来确保那些可读取的异步socket可以立即开始读取IO 
    #OS不停的搜索目前可以read的socket,有的话就返回rlist 
    rlist, _, _ = select.select(sockets, [], []) 
    for sock in rlist: 
      data = '' 
      while True: 
        try: 
          new_data = sock.recv(1024) 
        except socket.error, e: 
          if e.args[0] == errno.EWOULDBLOCK: 
            break 
          raise 
        else: 
          if not new_data: 
            break 
          else: 
            print new_data 
            data += new_data 
  
      task_num = sock2task[sock] 
      if not data: 
        sockets.remove(sock) 
        sock.close() 
        print 'Task %d finished' % task_num 
      else: 
        addr_fmt = format_address(sock.getpeername()) 
        msg = 'Task %d: got %d bytes of poetry from %s' 
        print msg % (task_num, len(data), addr_fmt) 
  
      poems[sock] += data 
  
  elapsed = datetime.datetime.now() - start 
  print 'Got poems in %s' % elapsed

结果只需要4秒就完成了读取任务。效率是刚才同步socket的三倍。对客户端的异步改造主要有两点:

同步模式下,客户端分别创建socket;而在异步模式下,client开始就创建了所有的socket。
通过“sock.setblocking(0)”设置socket为异步模式。
通过Unix系统的select俩返回可读取IO
最为核心的是26行和29行。尤其是29行的select操作返回待读取socket的列表。

Python 相关文章推荐
Python实现全局变量的两个解决方法
Jul 03 Python
Android模拟器无法启动,报错:Cannot set up guest memory ‘android_arm’ Invalid argument的解决方法
Jul 01 Python
numpy.random.seed()的使用实例解析
Feb 03 Python
详解多线程Django程序耗尽数据库连接的问题
Oct 08 Python
python实现生成字符串大小写字母和数字的各种组合
Jan 01 Python
Python面向对象封装操作案例详解 II
Jan 02 Python
win10下opencv-python特定版本手动安装与pip自动安装教程
Mar 05 Python
Pytorch mask-rcnn 实现细节分享
Jun 24 Python
Python绘图之二维图与三维图详解
Aug 04 Python
详解利用python识别图片中的条码(pyzbar)及条码图片矫正和增强
Nov 17 Python
用Python实现童年贪吃蛇小游戏功能的实例代码
Dec 07 Python
Python爬虫实战之爬取京东商品数据并实实现数据可视化
Jun 07 Python
Python开发的单词频率统计工具wordsworth使用方法
Jun 25 #Python
python 字典(dict)遍历的四种方法性能测试报告
Jun 25 #Python
用python登录Dr.com思路以及代码分享
Jun 25 #Python
python正则表达式re模块详解
Jun 25 #Python
Python通过websocket与js客户端通信示例分析
Jun 25 #Python
Flask框架学习笔记(一)安装篇(windows安装与centos安装)
Jun 25 #Python
Python中文编码那些事
Jun 25 #Python
You might like
PHP编程中字符串处理的5个技巧小结
2007/11/13 PHP
PHP中的按位与和按位或操作示例
2014/01/27 PHP
PHP解析目录路径的3个函数总结
2014/11/18 PHP
ThinkPHP模版引擎之变量输出详解
2014/12/05 PHP
微信公众号支付之坑:调用支付jsapi缺少参数 timeStamp等错误解决方法
2016/01/12 PHP
PHP和MySql中32位和64位的整形范围是多少
2016/02/18 PHP
PHP实现的简单分页类及用法示例
2016/05/06 PHP
jQuery 全选效果实现代码
2009/03/23 Javascript
基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)
2011/09/02 Javascript
提交表单时执行func方法实现代码
2013/03/17 Javascript
js简单实现交换Li的值
2014/05/22 Javascript
JavaScript动态改变HTML页面元素例如添加或删除
2014/08/10 Javascript
JavaScript 数组some()和filter()的用法及区别
2016/05/20 Javascript
省市联动效果的简单实现代码(推荐)
2016/06/06 Javascript
JavaScript判断浏览器对CSS3属性是否支持的多种方法
2016/11/13 Javascript
js面向对象编程总结
2017/02/16 Javascript
ES6扩展运算符用法实例分析
2017/10/31 Javascript
详解微信小程序之scroll-view的flex布局问题
2019/01/16 Javascript
js实现简单点赞操作
2020/03/17 Javascript
总结用Pdb库调试Python的方式及常用的命令
2016/08/18 Python
Python元组操作实例分析【创建、赋值、更新、删除等】
2017/07/24 Python
Python用61行代码实现图片像素化的示例代码
2018/12/10 Python
Python基于matplotlib画箱体图检验异常值操作示例【附xls数据文件下载】
2019/01/07 Python
解决Python 使用h5py加载文件,看不到keys()的问题
2019/02/08 Python
Python3.5常见内置方法参数用法实例详解
2019/04/29 Python
python for循环remove同一个list过程解析
2019/08/14 Python
python getpass模块用法及实例详解
2019/10/07 Python
css3实现文字首尾衔接跑马灯的示例代码
2020/10/16 HTML / CSS
澳洲小众品牌的集合网站:BNKR
2018/02/23 全球购物
经济系大学生求职信
2013/10/01 职场文书
高级工程师岗位职责
2013/12/15 职场文书
暑期社会实践学生的自我评价
2014/01/09 职场文书
寒假家长评语大全
2014/04/16 职场文书
自我检讨报告
2015/01/28 职场文书
《中国古代诗歌散文欣赏》高中语文教材
2019/08/20 职场文书
Redis 限流器
2022/05/15 Redis