一、协程技术
1.协程的概述
2.协程的优缺点
优点:
缺点:
3.基本用法
# time是默认阻塞
# 解决:能否修改非阻塞方式,在操作io的时候,立马切换到其他的协程运行!
# from gevent import monkey
# monkey.patch_all() # 解决:能否修改非阻塞方式,在操作io的时候,立马切换到其他的协程运行!
# import time
# import gevent
def f1():
for one in range(5):
print(f'f1 在运行---{one}')
time.sleep(1)
def f2():
for one in range(5):
print(f'f2 在运行---{one}')
time.sleep(1)
# 创建协程对象
# t1 = gevent.spawn(f1)
# t2 = gevent.spawn(f2)
# 运行
# gevent.joinall([t1, t2])
# ---------------------------------------
# 实例使用:tcp请求 socket;其他请求 requests
# ---------------------------------------
# time是默认阻塞
# 解决:能否修改非阻塞方式,在操作io的时候,立马切换到其他的协程运行!
from gevent import monkey
monkey.patch_all() # 解决:能否修改非阻塞方式,在操作io的时候,立马切换到其他的协程运行!
import time
import gevent
import requests
from datetime import datetime
def get_data(url):
print(f'{datetime.now()}-开始-GET-开始获取数据>>>')
resp = requests.get(url)
print(f'{datetime.now()}-结束-GET-开始获取数据>>>')
# get_data("http://vip.ytesting.com/")
# get_data("http://www.songqinnet.com/")
# 创建
gevent.joinall(
[gevent.spawn(get_data, "http://vip.ytesting.com/"),
gevent.spawn(get_data, "http://www.songqinnet.com/")]
)
print('执行结束')
二、协程实战(端口扫描)
# -----------------------------v5.0---------------------------------
'''
测试反馈:
1.是否可以自动识别ip或者域名---在输入的时候判断!
2.如果全扫描--发现很慢----------因为单线程跑,效率低---建议使用多线程、协程!
3.如果出现扫描结果不一样,可以使用取并集 set1 | set2 ----一个思路
优化方案:周期
1- 多线程/协程---并发操作
2- 做ip有效值判断
8.136.98.37
31990-32000
47.96.181.17
'''
# ------------------------------------------------------------------
import socket
import re
# 1- ip的有效判断-re 0.0.0.0~255.255.255.255
def check_ip(ip):
"""
:param ip:输入
:return:是否符合规则
"""
ip_address = re.compile(r'(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])')
if ip_address.match(ip) and len(ip) != 0:
return True
else:
return False
def check_domain(hostname):
"""
:param hostname:输入
:return:是否符合规则
"""
domainName = re.compile('[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?')
if domainName.match(hostname) and len(hostname) != 0:
return True
else:
return False
# 2- 直接使用ip-扫描
def scan_ip(ip):
# 2- 使用ip判断函数--判断
if check_ip(ip):
# 进入扫描端口
gevent_scan_port(ip)
else:
print('ip格式有误,请检查!')
# 3- 使用域名扫描
def domain_name_scan(domainName):
# 2- 可做域名判断
if 'http://' in domainName or 'https://' in domainName:
domainName = domainName[domainName.find("://")+3:] # 取前写后下标
print("正在解析的域名>>>", domainName)
# 2- 获取ip
server_ip = socket.gethostname()
print(f"该域名{domainName}的ip>>>{server_ip}")
gevent_scan_port(server_ip)
# 导出文件
def export_file(info):
fo = open("scanPort.txt", 'a', encoding='utf-8')
fo.write(info)
fo.close()
# 4- 端口扫描函数
def scan_port(ip, port): # 分段
# 访问成功是有返回值--是0
# 使用ip 实现tcp连接
sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sk.settimeout(0.5)
try:
conn = sk.connect_ex((ip, port)) # 有返回值('127.0.0.1', int型)
if conn == 0:
print(f'主机:{ip}, 端口:{port}已开放')
export_file(f'主机:{ip}, 端口:{port}已开放\n')
except:
pass
sk.close()
# 多线程-扫描
from gevent import monkey
monkey.patch_all()
import time
import gevent
import gevent.pool
def gevent_scan_port(ip):
start_time = time.time() # 开始计时
g = gevent.pool.Pool(500) # 限制协程的并发数量
export_file(f'主机:{ip},开始扫描......\n')
run_list = [] # 运行的协程
for port in range(1, 65535+1):
run_list.append(g.spawn(scan_port, ip, port))
gevent.joinall(run_list) # 运行完,主线程退出 阻塞
end_time = time.time()
print('端口扫描总共耗时>>>', end_time - start_time)
export_file(f'主机:{ip},扫描结束......\n')
# 5- 主入口
def main():
info = input('请选择ip或者域名>>>')
# 2- 接收用户输入
if check_ip(info):
# ip扫描
scan_ip(info)
elif check_domain(info):
# 域名扫描
domain_name_scan(info)
else:
print('输入有误!')
if __name__ == '__main__':
main()
扩展:
版本:V6.0
需求:
1、可以有操作的GUI页面
2、可以发送邮件:文件格式/字符串发送----安全