蛙蛙推荐:gevent并发发送UDP包演示

gevent是一个非常棒的python异步IO库,一般的示例都是用他来做高并发的tcp server,其实它也能很好的工作在udp上,而且超时,并发数都能很好的控制。

#!/usr/bin/env python
#
-*- coding:utf8 -*-

import DNS #http://pydns.sourceforge.net/
from gevent import spawn, joinall,socket,sleep
from gevent.coros import BoundedSemaphore
from datetime import datetime
import random

DNS.ParseResolvConf()
SERVER = (DNS.defaults['server'][0],53)
SERVER = ('8.8.8.8',53) #临时使用google的dns
TIMEOUT = 10
lock = BoundedSemaphore(50) #并发数限制,防止同时pending的请求太多

statis = {} #统计信息
def log(domain,status,responsetime):
statis.setdefault(status, 0)
statis[status] += 1
print '%s %s %s' % (domain, status, responsetime)

def getreq(domain, qtype):
'根据域名和查询类型得到dns请求的字节流'
m = DNS.Lib.Mpacker()
m.addHeader(id=random.randint(0,65535),
qr=0,
opcode=0,
aa=0,
tc=0,
rd=1,
ra=0,
z=0,
rcode=0,
qdcount=1,
ancount=0,
nscount=0,
arcount=0)
m.addQuestion(domain, qtype, DNS.Class.IN)
return m.getbuf()

def monitorone(domain):
try:
lock.acquire()

start = datetime.now()
client = socket.socket(
family=socket.AF_INET,
type=socket.SOCK_DGRAM,
proto=socket.IPPROTO_UDP)
client.settimeout(TIMEOUT)

req = getreq(domain, DNS.Type.MX) #封包
client.sendto(req, SERVER) #发包
(rsp, (ip, port)) = client.recvfrom(512) #收包
u = DNS.Lib.Munpacker(rsp) #解包
rsp = DNS.Lib.DnsResult(u, {})

end = datetime.now()
responsetime = (end - start).microseconds
log(domain, rsp.header['status'], responsetime)
except Exception, ex:
log(domain, ex.message, 0)
finally:
lock.release()

#加载域名列表并解析
list = [spawn(monitorone, domain.strip())
for domain in open('./domains.txt')]
joinall(list)
global statis
print statis

以上代码是从一个文本里加载一个域名列表,然后以50并发的速度去google dns查询DNS应答,记录应答状态码和响应时间。

 

posted @ 2011-12-03 10:18  蛙蛙王子  Views(3143)  Comments(1Edit  收藏  举报