我们用普通同步方式扫描10个端口,用协程(异步)方式扫描1000个端口,对比时间。

1、同步方式代码

#encoding=utf-8
#author: walker
#date: 2014-07-16
#function: 使用同步方式扫描10个端口

import time, socket, sys

def task(addr):
	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	sock.settimeout(100)
	try:
		sock.connect(addr)
		print('Port ' + str(str(addr[1])) + ' is  open')
	except:
		pass
	finally:
		sock.close()

#扫描10个端口
def synchronous():
	for i in range(0, 10):
		task(('127.0.0.1', i))
		
t0 = time.time()
synchronous()
t1 = time.time()
print('time: {}s'.format(t1 - t0))

walker机器的测试结果为9.0110001564s ≈ 9s 


2、协程(异步)方式代码

#encoding=utf-8
#author: walker
#date: 2014-07-16
#function: 使用协程(异步)方式扫描1000个端口

import gevent.monkey
gevent.monkey.patch_socket()

import gevent, socket, sys, time

def task(addr):
	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	sock.settimeout(100)
	try:
		sock.connect(addr)
		print('Port ' + str(str(addr[1])) + ' is  open')
	except:
		pass
	finally:
		sock.close()
		
#扫描1000个端口
def asynchronous():
	threads = []
	for i in range(0, 1000):
		threads.append(gevent.spawn(task, ('127.0.0.1', i)))
	gevent.joinall(threads)	

t0 = time.time()
asynchronous()
t1 = time.time()
print('time: {}s'.format(t1 - t0))

walker机器的测试结果为2.08499979973s ≈ 2s 


用同步方式扫描10个端口需要9s,而用协程扫描1000个端口仅需2s!从代码复杂性来看,asynchronous函数仅比synchronous函数多一行。也就是说协程以同步方式的代码复杂度实现了异步程序的性能!


Windows下使用gevent,建议安装二进制版本,先装greenlet,再装gevent:

http://www.lfd.uci.edu/~gohlke/pythonlibs/#greenlet

http://www.lfd.uci.edu/~gohlke/pythonlibs/#gevent


相关阅读:

1、Gevent tutorial中文翻译

2、Python协程:从yield/send到async/await


*** walker * 2014-07-16 ***