在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多进程同步简单实现代码
Apr 27 Python
Python实现将sqlite数据库导出转成Excel(xls)表的方法
Jul 17 Python
spyder常用快捷键(分享)
Jul 19 Python
Python基础学习之常见的内建函数整理
Sep 06 Python
Python生成数字图片代码分享
Oct 31 Python
python实现神经网络感知器算法
Dec 20 Python
对python中xlsx,csv以及json文件的相互转化方法详解
Dec 25 Python
Python多进程方式抓取基金网站内容的方法分析
Jun 03 Python
Pyqt5自适应布局实例
Dec 13 Python
nginx搭建基于python的web环境的实现步骤
Jan 03 Python
python ffmpeg任意提取视频帧的方法
Feb 21 Python
Python使用protobuf序列化和反序列化的实现
May 19 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 水平的题目
2007/05/30 PHP
php中DOMDocument简单用法示例代码(XML创建、添加、删除、修改)
2010/12/19 PHP
解析CI的AJAX分页 另类实现方法
2013/06/27 PHP
PHP图片处理之使用imagecopyresampled函数裁剪图片例子
2014/11/19 PHP
PHP和Mysql中转UTF8编码问题汇总
2015/10/10 PHP
Yii2中简单的场景使用介绍
2017/06/02 PHP
JS 删除字符串最后一个字符的实现代码
2014/02/20 Javascript
jquery默认校验规则整理
2014/03/24 Javascript
JavaScript在Android的WebView中parseInt函数转换不正确问题解决方法
2015/04/25 Javascript
一分钟理解js闭包
2016/05/04 Javascript
Nodejs中解决cluster模块的多进程如何共享数据问题
2016/11/10 NodeJs
angularjs中的$eval方法详解
2017/04/24 Javascript
JS基于正则表达式的替换操作(replace)用法示例
2017/04/28 Javascript
JS使用遮罩实现点击某区域以外时弹窗的弹出与关闭功能示例
2018/07/31 Javascript
JS实现中英文混合文字溢出友好截取功能
2018/08/06 Javascript
vue.js中ref和$refs的使用及示例讲解
2019/08/14 Javascript
使用easyui从servlet传递json数据到前端页面的两种方法
2019/09/05 Javascript
vue新建项目并配置标准路由过程解析
2019/12/09 Javascript
JavaScript switch语句使用方法简介
2019/12/30 Javascript
在Python中处理列表之reverse()方法的使用教程
2015/05/21 Python
python中defaultdict的用法详解
2017/06/07 Python
Python基于分水岭算法解决走迷宫游戏示例
2017/09/26 Python
用tensorflow实现弹性网络回归算法
2018/01/09 Python
python远程连接服务器MySQL数据库
2018/07/02 Python
python画图--输出指定像素点的颜色值方法
2019/07/03 Python
python中有关时间日期格式转换问题
2019/12/25 Python
浅谈Python中os模块及shutil模块的常规操作
2020/04/03 Python
TensorFlow使用Graph的基本操作的实现
2020/04/22 Python
opencv python 图片读取与显示图片窗口未响应问题的解决
2020/04/24 Python
CSS3贝塞尔曲线示例:创建链接悬停动画效果
2020/11/19 HTML / CSS
英国著名的化妆品折扣网站:Allbeauty.com
2016/07/21 全球购物
Blank NYC官网:夹克、牛仔裤等
2020/12/16 全球购物
小班重阳节活动方案
2014/02/08 职场文书
预备党员转正思想汇报
2014/09/26 职场文书
主持人开场白台词
2015/05/29 职场文书
Android自定义ScrollView实现阻尼回弹
2022/04/01 Java/Android