10月16日我写了一篇《用pcap和dpkt抓取url部分 》,这是个单进程做的,虽然说效率可以,但毕竟是一个进程。人嘛,总得追求完美,如果用多线程该怎么做呢?(我没有这方面经验)
我先是尝试多线程都去调用capture函数,发现得到的结果是多个重复的,也就是说,每个线程都去做了相同的事情;然后我想到是否可以有一个全局列表,一个线程写,另一个线程读,也失败,因为这样可能导致共享访问出问题。最后看书中发现了队列queue,它自己已经实现了数据保护,不需要我们额外考虑会不会冲突,ok,尝试吧。
写了两个类,一个抓包,一个分析
Code
1 #!/usr/bin/env python
2 #coding=utf-8
3 import pcap
4 import dpkt
5 import threading
6 from Queue import Queue
7 import time
8
9 TOTAL_HEADER_LENGTH = 48 #syn和ack包的数据长度是48,包含了8位选项
10 #
11 #class QueueWraper:
12 #
13 # def __init__(self):
14 # self.queue = Queue()
15 #
16 # def get():
17 # #debug
18 # return self.queue.get()
19 # def put(obj):
20 # #debug
21 # self.queue.put(obj)
22
23 class Capture(threading.Thread):
24
25 def __init__(self,threadname, queue, port):
26 threading.Thread.__init__(self,name = threadname)
27 self.sharedata = queue#queue
28 self.port = port
29
30 def run(self):
31 pc = pcap.pcap()
32 b = 'tcp port '+str(self.port)
33 pc.setfilter(b)
34 for ts,pkt in pc:
35 Eth = dpkt.ethernet.Ethernet(pkt)
36 length = Eth.data.len
37 if length > TOTAL_HEADER_LENGTH:
38 content = str(`Eth.data.data.data`)
39 self.sharedata.put(content)
40
41
42 class Makeresult(threading.Thread):
43
44 def __init__(self,threadname,queue,filepath):
45 threading.Thread.__init__(self,name = threadname)
46 self.sharedata = queue#queue
47 self.filepath = filepath
48 def run(self):
49 fp = open(self.filepath,'ab')
50 while True:
51 # fp = open(self.filepath,'ab')
52 urlist = self.sharedata.get()
53 if 'GET' in urlist:
54 print urlist
55 url = urlist.split()[1]
56 # print url
57 fp.write(url+'\r\n')
58 fp.flush()
59 # fp.close()
60 # time.sleep(1)
61
62 def main():
63 queue = Queue()
64 capture = Capture('capture', queue,80)
65 makeresult = Makeresult('makeresult', queue,'c:\\url.txt')
66 capture.start()
67 makeresult.start()
68
69 if __name__ == '__main__':
70 main()
71
72
73