在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实现命令行通讯录实例教程
Aug 18 Python
python中reduce()函数的使用方法示例
Sep 29 Python
Python爬虫使用Selenium+PhantomJS抓取Ajax和动态HTML内容
Feb 23 Python
PyQt5每天必学之事件与信号
Apr 20 Python
Django uwsgi Nginx 的生产环境部署详解
Feb 02 Python
在python中实现同行输入/接收多个数据的示例
Jul 20 Python
如何基于python3和Vue实现AES数据加密
Mar 27 Python
Python通过两个dataframe用for循环求笛卡尔积
Apr 29 Python
keras 模型参数,模型保存,中间结果输出操作
Jul 06 Python
python利用os模块编写文件复制功能——copy()函数用法
Jul 13 Python
class类在python中获取金融数据的实例方法
Dec 10 Python
python sleep和wait对比总结
Feb 03 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
常用星际术语索引(新手指南)
2020/03/04 星际争霸
PHP学习资料汇总与网址
2007/03/16 PHP
php smarty模版引擎中的缓存应用
2009/12/02 PHP
paypal即时到账php实现代码
2010/11/28 PHP
Javascript this关键字使用分析
2008/10/21 Javascript
学习ExtJS border布局
2009/10/08 Javascript
通过身份证号得到出生日期和性别的js代码
2009/11/23 Javascript
jquery插件制作 自增长输入框实现代码
2012/08/17 jQuery
jquery ajax jsonp跨域调用实例代码
2013/12/11 Javascript
js实现身份证号码验证的简单实例
2014/02/19 Javascript
Javascript堆排序算法详解
2014/12/03 Javascript
js实现百度联盟中一款不错的图片切换效果完整实例
2015/03/04 Javascript
javascript学习笔记之函数定义
2015/06/25 Javascript
js实现创建删除html元素小结
2015/09/30 Javascript
javascript实现对表格元素进行排序操作
2015/11/18 Javascript
JS实现table表格数据排序功能(可支持动态数据+分页效果)
2016/05/26 Javascript
设置jQueryUI DatePicker默认语言为中文
2016/06/04 Javascript
jQuery实现定位滚动条位置
2016/08/05 Javascript
用angular实现多选按钮的全选与反选实例代码
2017/05/23 Javascript
微信小程序实现类似微信点击语音播放效果
2020/03/30 Javascript
javascript中undefined的本质解析
2019/07/31 Javascript
基于jQuery实现可编辑的表格
2019/12/11 jQuery
python开发之list操作实例分析
2016/02/22 Python
python实现大转盘抽奖效果
2019/01/22 Python
python 画3维轨迹图并进行比较的实例
2019/12/06 Python
python 使用raw socket进行TCP SYN扫描实例
2020/05/05 Python
英国优质鞋类专家:Robinson’s Shoes
2017/12/08 全球购物
越南母婴用品购物网站:Kids Plaza
2020/04/09 全球购物
创伤外科专业推荐信范文
2013/11/19 职场文书
初婚初育证明
2014/01/14 职场文书
党员干部形式主义个人整改措施
2014/09/17 职场文书
简单的离婚协议书范本
2014/11/16 职场文书
幼儿园安全工作总结2015
2015/04/20 职场文书
幼儿园开学通知
2015/04/24 职场文书
2015中学教师个人工作总结
2015/07/22 职场文书
手把手教你实现PyTorch的MNIST数据集
2021/06/28 Python