在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中的index()方法使用教程
May 18 Python
Python字符串逐字符或逐词反转方法
May 21 Python
Python中return语句用法实例分析
Aug 04 Python
python虚拟环境virtualenv的安装与使用
Sep 21 Python
Python基于socket实现简单的即时通讯功能示例
Jan 16 Python
如何使用Python进行OCR识别图片中的文字
Apr 01 Python
pyinstaller打包opencv和numpy程序运行错误解决
Aug 16 Python
pyinstaller打包程序exe踩过的坑
Nov 19 Python
浅谈keras的深度模型训练过程及结果记录方式
Jan 24 Python
Python自动化测试笔试面试题精选
Mar 12 Python
python开发一个解析protobuf文件的简单编译器
Nov 17 Python
python数据库批量插入数据的实现(executemany的使用)
Apr 30 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 表单验证实现代码
2009/03/10 PHP
关于php mvc开发模式的感想
2011/06/28 PHP
php正则提取html图片(img)src地址与任意属性的方法
2017/02/08 PHP
JavaScript-世界上误解最深的语言分析
2007/08/12 Javascript
Javascript 倒计时源代码.(时.分.秒) 详细注释版
2011/05/09 Javascript
jQuery EasyUI API 中文文档 - EasyLoader 加载器
2011/09/29 Javascript
js获取指定日期前后的日期代码
2013/08/20 Javascript
js向上无缝滚动,网站公告效果 具体代码
2013/11/18 Javascript
jquery获得同源iframe内body下标签的值的方法
2014/09/25 Javascript
js兼容pc端浏览器并有多种弹出小提示的手机端浮层控件实例
2015/04/29 Javascript
在Mac OS下使用Node.js的简单教程
2015/06/24 Javascript
JavaScript基本语法学习教程
2016/01/14 Javascript
限制复选框最多选择项的实现代码
2016/05/30 Javascript
JS构造函数与原型prototype的区别介绍
2016/07/04 Javascript
JavaScript和jQuery制作光棒效果
2017/02/24 Javascript
原生JS+Canvas实现五子棋游戏实例
2017/06/19 Javascript
bootstrap treeview 扩展addNode方法动态添加子节点的方法
2017/11/21 Javascript
js+html5实现手机九宫格密码解锁功能
2018/07/30 Javascript
微信小程序在地图选择地址并返回经纬度简单示例
2018/12/03 Javascript
微信小程序合法域名配置方法
2019/05/06 Javascript
AJAX XMLHttpRequest对象创建使用详解
2020/08/20 Javascript
js+audio实现音乐播放器
2020/09/13 Javascript
pandas数值计算与排序方法
2018/04/12 Python
使用Python控制摄像头拍照并发邮件
2019/04/23 Python
numpy中的meshgrid函数的使用
2019/07/31 Python
python+openCV调用摄像头拍摄和处理图片的实现
2019/08/06 Python
解决python cv2.imread 读取中文路径的图片返回为None的问题
2020/06/02 Python
CSS3实现3D翻书效果
2016/06/20 HTML / CSS
Canvas环形饼图与手势控制的实现代码
2019/11/08 HTML / CSS
印度最好的在线药品订购网站:PharmEasy
2018/11/30 全球购物
职业生涯规划怎么写
2013/12/29 职场文书
给老师的检讨书
2014/02/11 职场文书
恶搞卫生巾广告词
2014/03/18 职场文书
驳回起诉裁定书
2015/05/19 职场文书
篮球赛闭幕式主持词
2015/07/03 职场文书
MySQL数据库中的锁、解锁以及删除事务
2022/05/06 MySQL