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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2290003.html

(0)
上一篇 2025年2月28日 00:03:53
下一篇 2025年2月18日 02:17:05

AD推荐 黄金广告位招租... 更多推荐

相关推荐

发表回复

登录后才能评论