用python编写nmap扫描工具--采用协程的方式

简介: 协程是一种轻量级的线程,协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。

 上一章节,我们采用多线程的技术去进行服务器端口的扫描,遗留了一些问题待优化,今天,我们采用协程的方式去尝试一下是否解决这个问题。

   

   协程是一种轻量级的线程,协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态。也就是说同一线程下的一段代码执行着执行着就可以中断,然后跳去执行另一段代码,当再次回来执行代码块的时候,接着从之前中断的地方开始执行。

   

协程的优点

1、执行效率高,尤其是在线程数较多的情况下,与多线程对比的优势更明显

2、不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好,因为执行效率比多线程高很多。

缺点

1、无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。

2、进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序


接下来,让我们通过一段代码来看一下运行的效果:

import gevent
from gevent import monkey
import time
def fun1():
    for num in range(3):
        print('fun1方法正在运行')
        #time.sleep(1)
def fun2():
    for num in range(3):
        print('fun2方法正在运行')
        #time.sleep(1)
# 创建协程对象
t1 = gevent.spawn(fun1)
t2 = gevent.spawn(fun2)
monkey.patch_all()
gevent.joinall([t1, t2])

以上代码执行的时候,输出结果如下:

fun1方法正在运行
fun1方法正在运行
fun2方法正在运行
fun2方法正在运行
fun2方法正在运行

是不是跟预想的不一样呢,是的,因为程序执行没有阻塞/中断,所以打印结果没有交叉打印 ,把time.sleep(1)放开后,再执行:

import gevent
from gevent import monkey
import time
def fun1():
    for num in range(3):
        print('fun1方法正在运行')
        time.sleep(1)  # 协程遇到耗时操作后会自动切换其他协程运行
def fun2():
    for num in range(3):
        print('fun2方法正在运行')
        time.sleep(1)  # 协程遇到耗时操作后会自动切换其他协程运行
# 创建协程对象
t1 = gevent.spawn(fun1)
t2 = gevent.spawn(fun2)
monkey.patch_all()
gevent.joinall([t1, t2])

打印结果如下:

fun1方法正在运行
fun2方法正在运行
fun1方法正在运行
fun2方法正在运行
fun1方法正在运行
fun2方法正在运行

代码说明:

本次采用gevent库实现协程的相关操作,在使用之前需要先安装该插件。

安装命令:pip install gevent

gevent.spawn()函数:创建协程对象

gevnet.joinall([传入携程对象列表]):会等待所有协程对象运行结束后再退出


接下来改造端口扫描的代码,采用协程的方式实现:

import socket
import time
import gevent
from gevent import monkey
from gevent.pool import Pool
monkey.patch_all()
def scan_port(host, port):
    sk = socket.socket()
    sk.settimeout(0.5)
    conn_result = sk.connect_ex((host, port))
    if conn_result == 0:
        print(f'服务器{host}的{port}端口已开放')
    sk.close()
def gevent_scan_host(host):
    # 8.129.162.225
    start_time = time.time()
    run_list = []
    g = Pool(200)   # 限制协程并发数量,单线程的,不要设置太大
    for port in range(0, 65536):
        run_list.append(g.spawn(scan_port, host, port))
    gevent.joinall(run_list)
    end_time = time.time()
    print(f'耗时:{end_time-start_time}')
host = input('请输入服务器ip地址:')
gevent_scan_host(host)

相关文章都是边学习边整理的笔记,如有错误,欢迎指正。如需进学习交流群,或者互相交流,文章催更,商务合作等,可添加微信xiaobotester ,记得备注一下。


相关文章
|
16天前
|
数据可视化 编译器 Python
Manim:数学可视化的强大工具 | python小知识
Manim(Manim Community Edition)是由3Blue1Brown的Grant Sanderson开发的数学动画引擎,专为数学和科学可视化设计。它结合了Python的灵活性与LaTeX的精确性,支持多领域的内容展示,能生成清晰、精确的数学动画,广泛应用于教育视频制作。安装简单,入门容易,适合教育工作者和编程爱好者使用。
78 7
|
1月前
|
JavaScript 前端开发 开发者
探索 DrissionPage: 强大的Python网页自动化工具
DrissionPage 是一个基于 Python 的网页自动化工具,结合了浏览器自动化的便利性和 requests 库的高效率。它提供三种页面对象:ChromiumPage、WebPage 和 SessionPage,分别适用于不同的使用场景,帮助开发者高效完成网页自动化任务。
130 4
|
1月前
|
开发者 Python
探索Python中的列表推导式:简洁而强大的工具
【10月更文挑战第41天】 在编程的世界中,效率与简洁是永恒的追求。本文将深入探讨Python编程语言中一个独特且强大的特性——列表推导式(List Comprehension)。我们将通过实际代码示例,展示如何利用这一工具简化代码、提升性能,并解决常见编程问题。无论你是初学者还是资深开发者,掌握列表推导式都将使你的Python之旅更加顺畅。
|
2月前
|
数据采集 数据可视化 数据挖掘
R语言与Python:比较两种数据分析工具
R语言和Python是目前最流行的两种数据分析工具。本文将对这两种工具进行比较,包括它们的历史、特点、应用场景、社区支持、学习资源、性能等方面,以帮助读者更好地了解和选择适合自己的数据分析工具。
51 2
|
2月前
|
C语言 开发者 Python
探索Python中的列表推导式:简洁而强大的工具
【10月更文挑战第21天】在Python的世界里,代码的优雅与效率同样重要。列表推导式(List Comprehensions)作为一种强大而简洁的工具,允许开发者通过一行代码完成对列表的复杂操作。本文将深入探讨列表推导式的使用方法、性能考量以及它如何提升代码的可读性和效率。
|
2月前
|
调度 Python
python知识点100篇系列(20)-python协程与异步编程asyncio
【10月更文挑战第8天】协程(Coroutine)是一种用户态内的上下文切换技术,通过单线程实现代码块间的切换执行。Python中实现协程的方法包括yield、asyncio模块及async/await关键字。其中,async/await结合asyncio模块可更便捷地编写和管理协程,支持异步IO操作,提高程序并发性能。协程函数、协程对象、Task对象等是其核心概念。
|
2月前
|
自然语言处理 算法 数据挖掘
探讨如何利用Python中的NLP工具,从被动收集到主动分析文本数据的过程
【10月更文挑战第11天】本文介绍了自然语言处理(NLP)在文本分析中的应用,从被动收集到主动分析的过程。通过Python代码示例,详细展示了文本预处理、特征提取、情感分析和主题建模等关键技术,帮助读者理解如何有效利用NLP工具进行文本数据分析。
55 2
|
2月前
|
测试技术 Python
Python MagicMock: Mock 变量的强大工具
Python MagicMock: Mock 变量的强大工具
55 4
|
2月前
|
存储 Python
python数据类型、debug工具(一)
python数据类型、debug工具(一)
|
1月前
|
NoSQL 关系型数据库 MySQL
python协程+异步总结!
本文介绍了Python中的协程、asyncio模块以及异步编程的相关知识。首先解释了协程的概念和实现方法,包括greenlet、yield关键字、asyncio装饰器和async/await关键字。接着详细讲解了协程的意义和应用场景,如提高IO密集型任务的性能。文章还介绍了事件循环、Task对象、Future对象等核心概念,并提供了多个实战案例,包括异步Redis、MySQL操作、FastAPI框架和异步爬虫。最后提到了uvloop作为asyncio的高性能替代方案。通过这些内容,读者可以全面了解和掌握Python中的异步编程技术。
49 0