在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编写vim插件
Nov 28 Python
python如何生成各种随机分布图
Aug 27 Python
python使用knn实现特征向量分类
Dec 26 Python
Python实现Selenium自动化Page模式
Jul 14 Python
对django layer弹窗组件的使用详解
Aug 31 Python
基于python实现学生信息管理系统
Nov 22 Python
python orm 框架中sqlalchemy用法实例详解
Feb 02 Python
Python装饰器的应用场景代码总结
Apr 10 Python
pip安装提示Twisted错误问题(Python3.6.4安装Twisted错误)
May 09 Python
python网络编程之五子棋游戏
May 14 Python
详解用selenium来下载小姐姐图片并保存
Jan 26 Python
python数字图像处理:图像简单滤波
Jun 28 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
有关phpmailer的详细介绍及使用方法
2013/01/28 PHP
基于PHP静态类的原罪详解
2013/05/06 PHP
php根据分类合并数组的方法实例详解
2013/11/06 PHP
PHP使用Redis实现防止大并发下二次写入的方法
2017/10/09 PHP
调用js时ie6和ie7,ff的区别
2009/08/19 Javascript
javascript显示用户停留时间的简单实例
2013/08/05 Javascript
javascript实现全角与半角字符的转换
2015/01/07 Javascript
jquery实现点击展开列表同时隐藏其他列表
2015/08/10 Javascript
全面理解JavaScript中的闭包
2016/05/12 Javascript
14 个折磨人的 JavaScript 面试题
2016/08/08 Javascript
使用vue编写一个点击数字计时小游戏
2016/08/31 Javascript
Bootstrapvalidator校验、校验清除重置的实现代码(推荐)
2016/09/28 Javascript
BootStrap表单宽度设置方法
2017/03/10 Javascript
Mongoose经常返回e11000 error的原因分析
2017/03/29 Javascript
js数组方法reduce经典用法代码分享
2018/01/07 Javascript
[02:26]2018DOTA2亚洲邀请赛赛前采访-Newbee篇
2018/04/03 DOTA
python获取当前用户的主目录路径方法(推荐)
2017/01/12 Python
基于Python和Scikit-Learn的机器学习探索
2017/10/16 Python
利用Python如何生成便签图片详解
2018/07/09 Python
python抓取搜狗微信公众号文章
2019/04/01 Python
python 的 scapy库,实现网卡收发包的例子
2019/07/23 Python
python3 map函数和filter函数详解
2019/08/26 Python
python+Django+pycharm+mysql 搭建首个web项目详解
2019/11/29 Python
新手入门学习python Numpy基础操作
2020/03/02 Python
借助Paramiko通过Python实现linux远程登陆及sftp的操作
2020/03/16 Python
使用 prometheus python 库编写自定义指标的方法(完整代码)
2020/06/29 Python
Python压缩模块zipfile实现原理及用法解析
2020/08/14 Python
利用python制作拼图小游戏的全过程
2020/12/04 Python
HTML5+CSS3实现无插件拖拽上传图片(支持预览与批量)
2017/01/05 HTML / CSS
2014年小班保育员工作总结
2014/12/23 职场文书
继承权公证书范本
2015/01/23 职场文书
入党积极分子考察意见
2015/06/02 职场文书
趣味运动会标语口号
2015/12/26 职场文书
2016年党课培训学习心得体会
2016/01/07 职场文书
Centos7中MySQL数据库使用mysqldump进行每日自动备份的编写
2021/08/02 MySQL
5个pandas调用函数的方法让数据处理更加灵活自如
2022/04/24 Python