在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中的__getitem__专有方法
Jun 27 Python
定制FileField中的上传文件名称实例
Aug 23 Python
TensorFlow搭建神经网络最佳实践
Mar 09 Python
Python多继承顺序实例分析
May 26 Python
python3.6下Numpy库下载与安装图文教程
Apr 02 Python
python实现微信防撤回神器
Apr 29 Python
Python 实现输入任意多个数,并计算其平均值的例子
Jul 16 Python
利用matplotlib实现根据实时数据动态更新图形
Dec 13 Python
Tensorflow Summary用法学习笔记
Jan 10 Python
Virtualenv 搭建 Py项目运行环境的教程详解
Jun 22 Python
python搜索算法原理及实例讲解
Nov 18 Python
k-means & DBSCAN 总结
Apr 27 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
用Zend Encode编写开发PHP程序
2006/10/09 PHP
php 学习资料零碎东西
2010/12/04 PHP
ajax 的post方法实例(带循环)
2011/07/04 PHP
smarty高级特性之过滤器的使用方法
2015/12/25 PHP
PHP7 弃用功能
2021/03/09 PHP
网页中返回顶部代码(多种方法)另附注释说明
2013/04/24 Javascript
javascript两种function的定义介绍及区别说明
2013/05/02 Javascript
js 获取范围内的随机数实例代码
2016/08/02 Javascript
js实现前端分页页码管理
2017/01/06 Javascript
JS匹配日期和时间的正则表达式示例
2017/05/12 Javascript
用node和express连接mysql实现登录注册的实现代码
2017/07/05 Javascript
JS事件绑定的常用方式实例总结
2019/03/02 Javascript
JS浏览器BOM常见操作实例详解
2020/04/27 Javascript
JS性能优化实现方法及优点进行
2020/08/30 Javascript
python 写的一个爬虫程序源码
2016/02/28 Python
python3通过selenium爬虫获取到dj商品的实例代码
2019/04/25 Python
Python-Seaborn热图绘制的实现方法
2019/07/15 Python
python3实现用turtle模块画一棵随机樱花树
2019/11/21 Python
浅谈django 重载str 方法
2020/05/19 Python
使用openCV去除文字中乱入的线条实例
2020/06/02 Python
keras的siamese(孪生网络)实现案例
2020/06/12 Python
HTML5 Canvas绘制圆点虚线实例
2015/01/01 HTML / CSS
澳大利亚手表品牌:Time IV Change
2018/10/06 全球购物
上海期货面试题
2014/01/31 面试题
介绍一下JNDI的基本概念
2013/07/26 面试题
生物技术专业研究生自荐信
2013/09/22 职场文书
大课间活动制度
2014/01/18 职场文书
广告创意求职信
2014/03/17 职场文书
蓝颜请假条
2014/04/11 职场文书
小学竞选班长演讲稿
2014/09/09 职场文书
计划生育证明格式范本
2014/09/12 职场文书
森马旗舰店双十一营销方案
2014/09/29 职场文书
会议主持词结束语
2015/07/03 职场文书
小学语文国培研修日志
2015/11/13 职场文书
MySQL学习必备条件查询数据
2022/03/25 MySQL
Elasticsearch 聚合查询和排序
2022/04/19 Python