在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使用心得之获得github代码库列表
Jun 25 Python
在Python中操作文件之truncate()方法的使用教程
May 25 Python
Python while、for、生成器、列表推导等语句的执行效率测试
Jun 03 Python
Python利用前序和中序遍历结果重建二叉树的方法
Apr 27 Python
使用Python画股票的K线图的方法步骤
Jun 28 Python
Flask使用Pyecharts在单个页面展示多个图表的方法
Aug 05 Python
用Python爬取QQ音乐评论并制成词云图的实例
Aug 24 Python
PyQt5+python3+pycharm开发环境配置教程
Mar 24 Python
Python requests.post方法中data与json参数区别详解
Apr 30 Python
Python中Yield的基本用法
Oct 18 Python
Python3自带工具2to3.py 转换 Python2.x 代码到Python3的操作
Mar 03 Python
Python面试不修改数组找出重复的数字
May 20 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插件 HTMLPurifier HTML解析器
2013/07/01 PHP
php文字水印和php图片水印实现代码(二种加水印方法)
2013/12/25 PHP
php使用array_rand()函数从数组中随机选择一个或多个元素
2014/04/28 PHP
php中有关合并某一字段键值相同的数组合并的改进
2015/03/10 PHP
使用php转义输出HTML到JavaScript
2015/03/27 PHP
ZF框架实现发送邮件的方法
2015/12/03 PHP
PHPCrawl爬虫库实现抓取酷狗歌单的方法示例
2017/12/21 PHP
关于取不到由location.href提交而来的上级页面地址的解决办法
2009/07/30 Javascript
IE图片缓存document.execCommand("BackgroundImageCache",false,true)
2011/03/01 Javascript
基于jquery的3d效果实现代码
2011/03/23 Javascript
JavaScript中的console.assert()函数介绍
2014/12/29 Javascript
Javascript数据结构与算法之列表详解
2015/03/12 Javascript
JS模拟并美化的表单控件完整实例
2015/08/19 Javascript
JS实现的新浪微博大厅文字内容滚动效果代码
2015/11/05 Javascript
jQuery validate+artdialog+jquery form实现弹出表单思路详解
2016/04/18 Javascript
只需五句话搞定JavaScript作用域(经典)
2016/07/26 Javascript
解决vue中使用Axios调用接口时出现的ie数据处理问题
2018/08/13 Javascript
解决前后端分离 vue+springboot 跨域 session+cookie失效问题
2019/05/13 Javascript
详细教你微信公众号正文页SVG交互开发技巧
2019/07/25 Javascript
vue页面加载时的进度条功能(实例代码)
2020/01/13 Javascript
vue+element实现动态加载表单
2020/12/13 Vue.js
python快速查找算法应用实例
2014/09/26 Python
利用 Monkey 命令操作屏幕快速滑动
2016/12/07 Python
基于ID3决策树算法的实现(Python版)
2017/05/31 Python
Python实现的堆排序算法示例
2018/04/29 Python
Python3.6中Twisted模块安装的问题与解决
2019/04/15 Python
Django发送邮件和itsdangerous模块的配合使用解析
2019/08/10 Python
python反转列表的三种方式解析
2019/11/08 Python
浅析canvas元素的html尺寸和css尺寸对元素视觉的影响
2019/07/22 HTML / CSS
销售岗位职责范本
2014/06/12 职场文书
党员群众路线剖析材料
2014/10/08 职场文书
人事行政主管岗位职责
2015/04/09 职场文书
关于分班的感言
2015/08/04 职场文书
2019送给家人们的中秋节祝福语
2019/08/15 职场文书
导游词之黄果树瀑布
2019/09/20 职场文书
《我的美好婚事》动画化决定纪念插画与先导PV公开
2022/04/06 日漫