在Python中使用异步Socket编程性能测试

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的列表。

(0)

相关推荐

  • Python 网络编程起步(Socket发送消息)

    一.服务端(Server.py)    服务端要做的事情是:    1. 创建一个Socket对象 Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->import sockets = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    2. 绑定一个端口 Code highlighting pro

  • python使用socket向客户端发送数据的方法

    本文实例讲述了python使用socket向客户端发送数据的方法.分享给大家供大家参考.具体如下: import socket, sys port = 55555 host = 'localhost' data = "test" * 10485760 # 40MB of data s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) byteswritten = 0 while byt

  • Python采用socket模拟TCP通讯的实现方法

    本文实例讲述了Python采用socket模拟TCP通讯的实现方法.分享给大家供大家参考.具体实现方法如下: 对于TCP server端的创建而言,分为如下几个步骤: 创建socket对象(socket):其中两个参数分别为Address Family(如AF_INET为IPV4,AF_INET6为IPV6,AF_UNIX为UNIX域协议族).socket类型(如SOCK_STREAM为TCP,SOCK_DGRAM为UDP). 绑定服务器地址(bind):参数为服务器地址二元组. 监听(list

  • python使用socket远程连接错误处理方法

    本文实例讲述了python使用socket远程连接错误处理方法.分享给大家供大家参考.具体如下: import socket, sys host = sys.argv[1] textport = sys.argv[2] filename = sys.argv[3] try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, e: print "Strange error creating sock

  • Python通过websocket与js客户端通信示例分析

    具体的 websocket 介绍可见 http://zh.wikipedia.org/wiki/WebSocket 这里,介绍如何使用 Python 与前端 js 进行通信. websocket 使用 HTTP 协议完成握手之后,不通过 HTTP 直接进行 websocket 通信. 于是,使用 websocket 大致两个步骤:使用 HTTP 握手,通信. js 处理 websocket 要使用 ws 模块: Python 处理则使用 socket 模块建立 TCP 连接即可,比一般的 soc

  • 在python中的socket模块使用代理实例

    说socket代理之前,先来说说http代理,python的urllib2是自带http代理功能的,可以用如下代码实现: 复制代码 代码如下: proxy_handler = urllib2.ProxyHandler({'http' : 'http://地址:端口'})opener = urllib2.build_opener(proxy_handler, urllib2.HTTPHandler)urllib2.install_opener(opener) 如此,接下来用urllib2来urlo

  • Python Socket编程详细介绍

    在使用Python做socket编程时,由于需要使用阻塞(默认)的方式来读取数据流,此时对于数据的结束每次都需要自己处理,太麻烦.并且网上也没找到太好的封装,所以就自己写了个简单的封装. 封装思路 1. 客户端每次请求均发送一个 SocketRequest 对象,其中封装具体的数据,这里使用json.对于要发送的数据,会自动添加一个结束符标识(EOF = '0x00'). 2. 服务器端接收数据时,根据结束符标识来生成完整的数据,并解包成 SocketRequest 对象. 3. 服务器端根据

  • python实现socket客户端和服务端简单示例

    复制代码 代码如下: import socket#socket通信客户端def client():    mysocket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)    mysocket.connect(('127.0.0.1',8000))    mysocket.send('hello')    while 1:        data=mysocket.recv(1024)        if data:           pri

  • python socket网络编程步骤详解(socket套接字使用)

    一.套接字套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象.它们允许程序接受并进行连接,如发送和接受数据.为了建立通信通道,网络通信的每个端点拥有一个套接字对象极为重要.套接字为BSD UNIX系统核心的一部分,而且他们也被许多其他类似UNIX的操作系统包括Linux所采纳.许多非BSD UNIX系统(如ms-dos,windows,os/2,mac os及大部分主机环境)都以库形式提供对套接字的支持.三种最流行的套接

  • Python使用Socket(Https)Post登录百度的实现代码

    登录百度,首先当然是先抓百度的登录包 ,由于是网页登录,最方便的自然是httpwatch了,我使用的测试账号是itiandatest1,密码是itianda,抓包结果: 复制代码 代码如下: POST /?login HTTP/1.1 Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/v

随机推荐