在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判断操作系统类型代码分享
Nov 22 Python
实例讲解Python设计模式编程之工厂方法模式的使用
Mar 02 Python
用python找出那些被“标记”的照片
Apr 20 Python
python 系统调用的实例详解
Jul 11 Python
Python读取文件内容的三种常用方式及效率比较
Oct 07 Python
对python .txt文件读取及数据处理方法总结
Apr 23 Python
Python操作json的方法实例分析
Dec 06 Python
对Python3中dict.keys()转换成list类型的方法详解
Feb 03 Python
利用Python进行图像的加法,图像混合(附代码)
Jul 14 Python
基于h5py的使用及数据封装代码
Dec 26 Python
Python+Kepler.gl实现时间轮播地图过程解析
Jul 20 Python
python中数组和列表的简单实例
Mar 25 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中的stdClass类
2014/04/18 PHP
WordPress中用于获取文章作者与分类信息的方法整理
2015/12/17 PHP
Zend Framework教程之动作的基类Zend_Controller_Action详解
2016/03/07 PHP
php支付宝在线支付接口开发教程
2016/09/19 PHP
thinkphp下MySQL数据库读写分离代码剖析
2017/04/18 PHP
myFocus slide3D v1.1.0 使用方法与下载
2011/01/12 Javascript
jquery实现倒计时代码分享
2014/06/13 Javascript
详解maxlength属性在textarea里奇怪的表现
2015/12/27 Javascript
分享jQuery插件的学习笔记
2016/01/14 Javascript
微信小程序购物商城系统开发系列-目录结构介绍
2016/11/21 Javascript
jquery实现简单的瀑布流布局
2016/12/11 Javascript
本地Bootstrap文件字体图标引入却无法显示问题的解决方法
2020/04/18 Javascript
vue-router3.0版本中 router.push 不能刷新页面的问题
2018/05/10 Javascript
Vue无限滑动周选择日期的组件的示例代码
2018/07/18 Javascript
vue权限问题的完美解决方案
2019/05/08 Javascript
js纯前端实现腾讯cos文件上传功能的示例代码
2019/05/14 Javascript
微信小程序实现渐入渐出动画效果
2019/06/13 Javascript
js实现页面多个日期时间倒计时效果
2019/06/20 Javascript
vue中实现Monaco Editor自定义提示功能
2019/07/05 Javascript
使用JS location实现搜索框历史记录功能
2019/12/23 Javascript
python写的一个文本编辑器
2014/01/23 Python
python 定时修改数据库的示例代码
2018/04/08 Python
python对象与json相互转换的方法
2019/05/07 Python
Python异常原理及异常捕捉实现过程解析
2020/03/25 Python
python中matplotlib实现随鼠标滑动自动标注代码
2020/04/23 Python
如何通过python计算圆周率PI
2020/11/11 Python
AmazeUI底部导航栏与分享按钮的示例代码
2020/08/18 HTML / CSS
工作表扬信的范文
2014/01/10 职场文书
乔迁宴答谢词
2014/01/21 职场文书
关于毕业的中学校园广播稿
2014/01/26 职场文书
运动会通讯稿100字
2014/01/31 职场文书
商业计算机应用专业自荐书
2014/06/09 职场文书
无房产证房屋转让协议书合同样本
2014/10/18 职场文书
教代会开幕词
2015/01/28 职场文书
销售员岗位职责范本
2015/04/11 职场文书
2016年校园社会综合治理宣传月活动总结
2016/03/16 职场文书