port扫描仪的原理非常easy。没有什么比操作更socket,能够connect它认为,port打开。

import socket
def scan(port):
s = socket.socket()
if s.connect_ex(('localhost', port)) == 0:
print port, 'open'
s.close()
if __name__ == '__main__':
map(scan,range(1,65536))

这样一个最简单的端口扫描器出来了。

等等喂,半天都没反应,那是由于socket是堵塞的,每次连接要等非常久才超时。

我们自己给它加上的超时。

s.settimeout(0.1)

再跑一遍,感觉快多了。

多线程版本号

import socket
import threading
def scan(port):
s = socket.socket()
s.settimeout(0.1)
if s.connect_ex(('localhost', port)) == 0:
print port, 'open'
s.close() if __name__ == '__main__':
threads = [threading.Thread(target=scan, args=(i,)) for i in xrange(1,65536)]
map(lambda x:x.start(),threads)

执行一下,哇,好快,快到抛出错误了。thread.error: can't start new thread。

想一下,这个进程开启了65535个线程,有两种可能。一种是超过最大线程数了,一种是超过最大socket句柄数了。在linux能够通过ulimit来改动。

假设不改动最大限制,怎么用多线程不报错呢?

加个queue,变成生产者-消费者模式,开固定线程。

多线程+队列版本号

import socket
import threading
from Queue import Queue
def scan(port):
s = socket.socket()
s.settimeout(0.1)
if s.connect_ex(('localhost', port)) == 0:
print port, 'open'
s.close() def worker():
while not q.empty():
port = q.get()
try:
scan(port)
finally:
q.task_done() if __name__ == '__main__':
q = Queue()
map(q.put,xrange(1,65535))
threads = [threading.Thread(target=worker) for i in xrange(500)]
map(lambda x:x.start(),threads)
q.join()

这里开500个线程,不停的从队列取任务来做。

multiprocessing+队列版本号

总不能开65535个进程吧?还是用生产者消费者模式

import multiprocessing
def scan(port):
s = socket.socket()
s.settimeout(0.1)
if s.connect_ex(('localhost', port)) == 0:
print port, 'open'
s.close() def worker(q):
while not q.empty():
port = q.get()
try:
scan(port)
finally:
q.task_done() if __name__ == '__main__':
q = multiprocessing.JoinableQueue()
map(q.put,xrange(1,65535))
jobs = [multiprocessing.Process(target=worker, args=(q,)) for i in xrange(100)]
map(lambda x:x.start(),jobs)

注意这里把队列作为一个參数传入到worker中去,由于是process safe的queue。不然会报错。

还实用的是JoinableQueue()。顾名思义就是能够join()的。

gevent的spawn版本号

from gevent import monkey; monkey.patch_all();
import gevent
import socket
...
if __name__ == '__main__':
threads = [gevent.spawn(scan, i) for i in xrange(1,65536)]
gevent.joinall(threads)

注意monkey patch必须在被patch的东西之前import,不然会Exception KeyError.比方不能先import threading,再monkey patch.

gevent的Pool版本号

from gevent import monkey; monkey.patch_all();
import socket
from gevent.pool import Pool
...
if __name__ == '__main__':
pool = Pool(500)
pool.map(scan,xrange(1,65536))
pool.join()

concurrent.futures版本号

import socket
from Queue import Queue
from concurrent.futures import ThreadPoolExecutor
...
if __name__ == '__main__':
q = Queue()
map(q.put,xrange(1,65536))
with ThreadPoolExecutor(max_workers=500) as executor:
for i in range(500):
executor.submit(worker,q)

版权声明:本文博客原创文章。博客,未经同意,不得转载。

流动python - 写port扫描仪和各种并发尝试(多线程/多进程/gevent/futures)的更多相关文章

  1. Python多线程多进程那些事儿看这篇就够了~~

    自己以前也写过多线程,发现都是零零碎碎,这篇写写详细点,填一下GIL和Python多线程多进程的坑~ 总结下GIL的坑和python多线程多进程分别应用场景(IO密集.计算密集)以及具体实现的代码模块 ...

  2. 【Python】如何基于Python写一个TCP反向连接后门

    首发安全客 如何基于Python写一个TCP反向连接后门 https://www.anquanke.com/post/id/92401 0x0 介绍 在Linux系统做未授权测试,我们须准备一个安全的 ...

  3. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

  4. 教你用python写:HDU刷题神器

    声明:本文以学习为目的,请不要影响他人正常判题 HDU刷题神器,早已被前辈们做出来了,不过没有见过用python写的.大一的时候见识了学长写这个,当时还是一脸懵逼,只知道这玩意儿好屌-.时隔一年,决定 ...

  5. python写的一个集合

    起因:原本打算用python写一个抢火车票的脚本.在那 期间遇见各种浏览器驱动失败的节奏....打算先缓一下 然后就去写集合了. 0x01 源码: # -*- coding:'utf-8' -*- # ...

  6. python多进程并发和多线程并发和协程

    为什么需要并发编程? 如果程序中包含I/O操作,程序会有很高的延迟,CPU会处于等待状态,这样会浪费系统资源,浪费时间 1.Python的并发编程分为多进程并发和多线程并发 多进程并发:运行多个独立的 ...

  7. Python 网站后台扫描脚本

    Python  网站后台扫描脚本 #!/usr/bin/python #coding=utf-8 import sys import urllib import time url = "ht ...

  8. 用python写MapReduce函数——以WordCount为例

    尽管Hadoop框架是用java写的,但是Hadoop程序不限于java,可以用python.C++.ruby等.本例子中直接用python写一个MapReduce实例,而不是用Jython把pyth ...

  9. 十行代码--用python写一个USB病毒 (知乎 DeepWeaver)

    昨天在上厕所的时候突发奇想,当你把usb插进去的时候,能不能自动执行usb上的程序.查了一下,发现只有windows上可以,具体的大家也可以搜索(搜索关键词usb autorun)到.但是,如果我想, ...

随机推荐

  1. mysqldump 命令的使用

    1.导出结构不导出数据 mysqldump -d databasename -uroot -p > xxx.sql 2.导出数据不导出结构 mysqldump -t databasename - ...

  2. WPF 3D:简单的Point3D和Vector3D动画创造一个旋转的正方体

    原文:WPF 3D:简单的Point3D和Vector3D动画创造一个旋转的正方体 运行结果: 事实上很简单,定义好一个正方体,处理好纹理.关于MeshGeometry3D的正确定义和纹理这里就不多讲 ...

  3. 【原创】只学到二维数组和结构体,不用链表也能写一个C贪食蛇?(四)

    全系列Index: [原创]只学到二维数组和结构体,不用链表也能写一个C贪食蛇?(一) [原创]只学到二维数组和结构体,不用链表也能写一个C贪食蛇?(二) [原创]只学到二维数组和结构体,不用链表也能 ...

  4. django1.7 配置demo教程(环境搭建)

    近期又用到django做个简单项目,1年多没用过了有些手生,按理说没啥问题吧 以下是一个简单的环境搭建demo过程: 前提条件:准备了python2.7已经安装 1.搭建django环境下载 http ...

  5. UVA 12103 - Leonardo's Notebook(数论置换群)

    UVA 12103 - Leonardo's Notebook 题目链接 题意:给定一个字母置换B.求是否存在A使得A^2=B 思路:随意一个长为 L 的置换的k次幂,会把自己分裂成gcd(L,k) ...

  6. NOI 评价体系 arbiter 安装方法 常见的问题 移植

    #!/bin/bash AppPath="$PWD"   读取当前文件夹 echo "Arbiter is installing..." sudo apt-ge ...

  7. POJ 1019 Number Sequence 解读

    这是一个看似简单,其实很难受. 本来我想发挥它的标题轨道基础.没想到反被消遣-_-|||. 看它在个人基础上,良好的数学就干脆点,但由于过于频繁,需求将被纳入全,因此,应该难度4星以上. 方法就是直接 ...

  8. php学习笔记--高级教程--读取文件、创建文件、写入文件

    打开文件:fopen:fopen(filename,mode);//fopen("test.txt","r"): 打开模式:r  仅仅读方式打开,将文件指针指向 ...

  9. Solr在结果返回函数值

    如果你有一个服务,你的用户能够搜索不同的公司.用户输入一个简单的keyword,能够返回匹配keyword的公司,可是有一天,用户要求返回的公司列表中能够显示公司跟用户的距离,这是该怎么做呢? 1.如 ...

  10. Linux下一个Nginx安装步骤

    一个.下载pcre 官网下载:http://www.pcre.org/ # wget http://sourceforge.net/projects/pcre/files/pcre/8.35/pcre ...