1.IO 多路复用

1.监听多个socket变化

2.socket服务端

IO多路复用+socket 来实现web服务器:

  • a.服务端优先运行
  • b.浏览器:http://.......com

    浏览器连接服务器就是socket + send("http协议")
  • c.服务端获取客户端发来的url,根据url不同响应数据
  • d.断开连接

产出:

  • a.浏览器发送数据,需要按照指定规则
  • b.监听多个socket对象
  • c.web框架开发者,业务开发者
  • d.模块独立化
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Date: 2017/3/27 import select
import socket s1 = socket.socket()
s1.setblocking(0)
s1.bind(("127.0.0.1", 8888,))
s1.listen(5) inputs = [s1, ]
while True:
r_list, w_list, e_list = select.select(inputs, [], [], 0.5) for client in r_list:
if client == s1:
conn, addr = client.accept()
conn.setblocking(0)
inputs.append(conn)
else:
data = bytes()
while True:
try:
chunk = client.recv(1024) except Exception as e:
chunk = None
if not chunk:
break
data += chunk data_str = data.decode() '''print(data_str)
客户端请求过来的数据原型
GET /login.html HTTP/1.1
Host: 127.0.0.1:8888
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8
'''
header, body = data_str.split("\r\n\r\n", 1) # 找到第一个\r\n\r\n 将请求进行分割;上半部为请求头,下半部为请求体
head_list = header.split("\r\n") # 将“请求头”进行分割为一行行的请求行数据; '''print(head_list)
通过“\r\n\r\n”切分过后的请求头数据
['GET /login.html HTTP/1.1', 'Host: 127.0.0.1:8888', 'Connection: keep-alive', 'Cache-Control: max-age=0', \
'Upgrade-Insecure-Requests: 1', \
'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', \
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding: gzip,\
deflate, sdch, br', 'Accept-Language: zh-CN,zh;q=0.8']
''' head_dict = {} # 将请求头数据 切分为字典格式head_dict for line in head_list:
value = line.split(":", 1) # 将请求头,按照第一个“:”进行分割
if len(value) == 2: # 如果分割为两份
k, v = value # 第一份设置为 k ,第二份为 v
head_dict[k] = v # 将第一段的k,设置值为 v
else: # 处理请求头的第一行 "GET /login.html HTTP/1.1" 按照空格切分;
head_dict["get"], head_dict["url"], head_dict["HTTP"] = line.split(" ") # 将切分的3部分分别赋值; '''print(head_dict)
切分后的请求头,字典格式 head_dict
{'Accept-Encoding': ' gzip, deflate, sdch, br', \
'Accept': ' text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', \
'Upgrade-Insecure-Requests': ' 1', \
'url': '/login.html', \
'Host': ' 127.0.0.1:8888', \
'Cache-Control': ' max-age=0', \
'Connection': ' keep-alive', \
'get': 'GET', \
'User-Agent': ' Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', \
'HTTP': 'HTTP/1.1', \
'Accept-Language': ' zh-CN,zh;q=0.8'}
'''

3.socket 客户端(爬虫)

利用一个线程,同时发送n个请求实现(异步非堵塞模块)

a.循环列表,为每一个URL生成一个Socket对象

b.每一个socket对象,向远程发送链接请求

  • connect: 会堵塞

    c.如果连接上:
  • 发送数据时,需要遵循HTTP的格式;

    d.获取相应内容

    e.关闭

注意:可读可写的状态

产出:

a.setblocking(0) # 以前夯住的地方都会报错

b.select 监听其他对象,需要有个 def fileno(self): 函数

c.gevent, twisted, asycio ---> 单线程并发发送http请求;


import socket
import select class Foo:
def __init__(self, s1, callback, url ,host):
self.s1 = s1
self.callback = callback
self.url = url
self.host = host def fileno(self):
return self.s1.fileno() class NbIO:
def __init__(self):
self.fds = []
self.connections = [] def connect(self, url_list):
for item in url_list:
conn = socket.socket()
conn.setblocking(0) # 表示连接不堵塞,不等待服务端返回数据
try:
conn.connect((item["host"], 80)) # 客户端连接 服务端 connect
except BlockingIOError as e:
pass
obj = Foo(conn, item["callback"], item["url"], item["host"])
self.fds.append(obj)
self.connections.append(obj) def send(self):
while True:
try:
if len(self.fds) == 0:
return
r_list, w_list, e_list = select.select(self.fds, self.connections, [], 0.5)
if len(self.fds) == 0:
break
for obj in r_list:
# 有数据响应回来
conn = obj.s1 data = bytes()
while True:
try:
d = conn.recv(1024)
data += d
except BlockingIOError as e:
d = None
if not d:
break
# print(data.decode())
obj.callback(data)
self.fds.remove(obj) for obj in w_list:
# 已经连接到远程
conn = obj.s1 template = "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n" % (obj.url, obj.host, )
conn.sendall(template.encode()) # print(conn)
self.connections.remove(obj)
except OSError as e:
pass def f1(data):
print(data.decode()) def f2(data):
print(data) url_list = [
{'host':"www.baidu.com",'url': '/','callback':f1 }, # socket
{'host':"www.bing.com",'url': '/','callback':f2 },
{'host':"www.cnblogs.com",'url': '/wupeiqi','callback':f1 },
] obj = NbIO()
obj.connect(url_list)
obj.send()

2.Paramiko模块,按照SSH协议连接数据以及发送数据;

1.可以通过python代码,实现对远程服务器操作;

2.功能:

  • a.使用用户名密码:命令,文件
  • b.使用用户名秘钥:命令,文件
  • c.执行创建session

2.1使用基于用户名密码的连接:

1.通过SSH Client方式连接:

import paramiko

ssh = paramiko.SSHClient()            # 创建SSh对象
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 允许连接不在know_hosts文件中的主机
ssh.connect(hostname="192.168.56.11", port=22, username="root", password="123456") # 创建连接
stdin, stdout, stderr = ssh.exec_command("df -h") # 执行命令
result = stdout.read() # 获取命令结果 print(result.decode()) # 打印获取的命令结果
ssh.close() # 关闭连接

2.通过SSHClient 封装 Transport方式连接

import paramiko

transport = paramiko.Transport(('192.168.56.11', 22))
transport.connect(username='root', password='123456') ssh = paramiko.SSHClient()
ssh._transport = transport stdin, stdout, stderr = ssh.exec_command('df -h') result = stdout.read()
print(result.decode()) ssh.close()

以上输出:

文件系统        容量  已用  可用 已用% 挂载点
/dev/sda3 48G 13G 36G 26% /
devtmpfs 903M 0 903M 0% /dev
tmpfs 912M 0 912M 0% /dev/shm
tmpfs 912M 33M 880M 4% /run
tmpfs 912M 0 912M 0% /sys/fs/cgroup
/dev/sda1 197M 182M 15M 93% /boot
tmpfs 183M 0 183M 0% /run/user/0

3.基于私钥字符串进行连接

import paramiko

private_key = paramiko.RSAKey.from_private_key_file(r'C:\Users\admin\.ssh\id_rsa')

transport = paramiko.Transport(('192.8.21.100',22))
transport.connect(username='root', pkey=private_key) ssh = paramiko.SSHClient()
ssh._transport = transport
while True:
cmd = input(">>:")
if not cmd:continue
if cmd == "exit":break
stdin, stdout, stderr = ssh.exec_command(cmd) stderrad = stderr.read()
result=stdout.read()
print(result.decode('utf-8'),stderrad.decode("utf-8")) transport.close()

2.2SFTPClient基于用户名密码上传下载

1.用于连接远程服务器并执行上传下载

import paramiko

transport = paramiko.Transport(('192.168.56.11', 22))
transport.connect(username='root', password='123456') sftp = paramiko.SFTPClient.from_transport(transport) # 创建sftp连接 # sftp.put('/tmp/location.py', '/tmp/test.py') # 将location.py 上传至服务器 /tmp/test.py
sftp.get('a.py', 'a.py') # 将远程家目录下的a.py 下载到本地当前目录 a.py
transport.close()

2.通过paramiko封装 Transport方式进行模块化封装

import paramiko

class SshHelp:

    def __init__(self, host, port, username, pwd):
self.host = host
self.port = port
self.username = username
self.pwd = pwd
self.transport = None def connect(self):
transport = paramiko.Transport((self.host, self.port, ))
transport.connect(username=self.username, password=self.pwd)
self.transport = transport def upload(self, yuan, local):
sftp = paramiko.SFTPClient.from_transport(self.transport)
sftp.get(yuan, local) def cmd(self, shell):
ssh = paramiko.SSHClient()
ssh._transport = self.transport stdin, stdout, stderr = ssh.exec_command(shell)
result = stdout.read()
print(result.decode()) def close(self):
self.transport.close() if __name__ == '__main__': obj = SshHelp("192.168.56.11", 22, "root", "123456")
obj.connect()
obj.cmd("df -h") obj.upload("a.py", "a.py") obj.close()

3.MySQL的操作连接

1.什么是MySQL:

服务端:

a.socket服务端运行,监听,IP和端口

b.获取客户端发送的数据:select inset...

c.解析

d.去文件中操作

客户端:

a.socket客户端:基于各种语言的客户端

b.验证

c.发送命令(SQL语句)

3.1表的操作:

1.创建一个表tb1:

not null:        表示不能为空;
auto_increment: 表示为自增(一个表只能有一个自增的列)
primary key: 主键(是一种索引,查询速度快,有约束的功能表示这一列不能为空、不能重复)
default: 表示为默认值;在为空时设置一个默认值;
create table tb1(
-> id int not null auto_increment primary key,
-> name char(20) null,
-> age int not null)engine=innodb default charset utf8;

2.单外键,一个字符串+约束foreign key;

constraint:    约束、关键字
fk_cc: 名字
foreign key: 关键字
(deparment_id): 本(自)表中的字段deparment_id
references: 关键字
deparment(id): 来自于deparment表里的id列
create table deparment(
id int not null auto_increment primary key,
title char(32) null
) create table person(
id int not null auto_increment primary key,
username char(32) null ,
age int not null,
deparment_id int not null,
constraint fk_cc foreign key (deparment_id) references deparment(id)
)

3.多项的外键,一个表对多个表的外键

create table deparment(
id int not null auto_increment primary key,
title char(32) null
) create table host(
id int not null auto_increment primary key,
ip char(32) null,
port char(32) null
) create table de_2_host(
id int not null auto_increment primary key,
did int not null,
hid int not null,
constraint fk_did_deparment foreign key (did) references deparment(id),
constraint fk_hid_host foreign key (hid) references host(id)
)

4.连表操作,查询a表关联b表,其中a表里的deparment_id和b表里的id相等:

SELECT * FROM a表 LEFT JOIN b表 ON a表.deparment_id = b表.id;

3.2使用pymysql实现连接数据库:

import pymysql

conn = pymysql.connect(host="192.168.56.11", port=3306, user="baolin", passwd="123456", db="python16")   # 创建连接

# cursor = conn.cursor()                                   # 创建游标(默认为元组形式)
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 创建游标(会依照字典的格式展现) # 执行sql时不要使用字符串拼接(以免SQL注入)
effect_row = cursor.execute("SELECT id,name,age FROM tb1 WHERE id > %s", (2,)) # 执行SQL,并返回受影响行数;
# effect_row = cursor.executemany("insert into tb1(name,age)VALUES(%s,%s)", [("xiaoliu", 17), ("tianpeng", 23),]) '''不可用:
username = inpus(>>>:)
pwd = inpus(>>>:)
sql = "select * from tb1 username = %s and pwd = %s" %(username,username)
effect_row = cursor.execute(sql)
如果用户输入的用户:root or 1 == 1 --
得到的语句为:(mysql中--为注释)一下语句就会永远成立
select * from tb1 username = root or 1 == 1 -- and pwd = %s"
'''
# ret = cursor.fetchone() # 获取第一条数据
# ret = cursor.fetchmany(3) # 获取内容的前三行
ret = cursor.fetchall() # 获取所有数据
conn.commit() # 提交操作
print(ret)
cursor.close() # 关闭游标
conn.close() # 关闭连接 new_id = cursor.lastrowid # 涉及到插入时,求出最后插入那条数据的自增ID
print(new_id)

012-Python-paramiko和IO多路复用的更多相关文章

  1. python 网络编程 IO多路复用之epoll

    python网络编程——IO多路复用之epoll 1.内核EPOLL模型讲解     此部分参考http://blog.csdn.net/mango_song/article/details/4264 ...

  2. python网络编程——IO多路复用之select

    1 IO多路复用的概念 原生socket客户端在与服务端建立连接时,即服务端调用accept方法时是阻塞的,同时服务端和客户端在收发数据(调用recv.send.sendall)时也是阻塞的.原生so ...

  3. python中的IO多路复用

    在python的网络编程里,socetserver是个重要的内置模块,其在内部其实就是利用了I/O多路复用.多线程和多进程技术,实现了并发通信.与多进程和多线程相比,I/O多路复用的系统开销小,系统不 ...

  4. socket_server源码剖析、python作用域、IO多路复用

    本节内容: 课前准备知识: 函数嵌套函数的使用方法: 我们在使用函数嵌套函数的时候,是学习装饰器的时候,出现过,由一个函数返回值是一个函数体情况. 我们在使用函数嵌套函数的时候,最好也这么写. def ...

  5. Python实战之IO多路复用select的详细简单练习

    IO多路复用 I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. select   它通过一个select()系统调用来 ...

  6. day36 python学习gevent io 多路复用 socketserver *****

    ---恢复内容开始--- gevent 1.切换+保存状态 2.检测单线程下任务的IO,实现遇到IO自动切换 Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在geven ...

  7. python之路 IO多路复用 线程进程初步了解

    一.IO多路复用 1.客户端 #!/usr/bin/env python #-*-coding:utf-8-*- import socket sk=socket.socket() sk.connect ...

  8. python day 15: IO多路复用,socketserver源码培析,

    目录 python day 15 1. IO多路复用 2. socketserver源码分析 python day 15 2019/10/20 学习资料来自老男孩教育 1. IO多路复用 ''' I/ ...

  9. Python自动化之IO多路复用

    单线程.多线程和异步对比图 灰色的是阻塞 IO多路复用 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心 ...

  10. python学习之-- IO多路复用 select模块

    python I/O多路复用包括3个模块,上一篇已经说过概念,这里我使用的是select模块实现一个ftp并发 服务器端核心代码: import socket,select import queue, ...

随机推荐

  1. Mysql事务与JDBC事务管理

    一.事务概述 1.什么是事务 一件事情有n个组成单元 要不这n个组成单元同时成功 要不n个单元就同时失败 就是将n个组成单元放到一个事务中 2.mysql的事务 默认的事务:一条sql语句就是一个事务 ...

  2. 链接器link.exe 编译器cl.exe 资源编译器rc.exe

    原文地址:https://blog.csdn.net/biggbang/article/details/24433065 1.cl.exe文件是Visual C\C++的编译器,它将程序源代码文件编译 ...

  3. 专题:DP杂题1

    A POJ 1018 Communication System B POJ 1050 To the Max C POJ 1083 Moving Tables D POJ 1125 Stockbroke ...

  4. gnutls-3.5.18 static building for windows

    gnutls-3.5.18 static building for windows Required libraries:1. libnettle 2. gmplib Optional librari ...

  5. Vue 介绍,优点,实例

    一 认识vue 1.什么是vue 以数据驱动的web渐进式框架 三大主流框架: Angular React Vue 设计模式:MVVM 2.vue优点 - 以数据驱动,不直接操作DOM,效率高- 单页 ...

  6. Golang -- range小坑铭记

    废话少叙,先上一段代码,猜猜预期的效果. package main import ( "fmt" ) type student struct { Name string Age i ...

  7. Mysql 数据库增删改查

    数据插入 语法:INSERT INTO Table_name(field1,field2……fieldN) values(value1,vlaue2,…valueN) 单行插入用户类型 INSERT ...

  8. MD5算法工具类

    抽时间写了一个算法工具类,目前支持的算法有SHA1,SHA256,SHA384,SHA512,MD5,同时支持获取文件的MD5值. 使用方法如下: 获取字符串的MD5值 String str= Alg ...

  9. JAVA实现网络文件下载

    HttpURLConnection conn = null; OutputStream outputStream = null; InputStream inputStream = null; try ...

  10. JS如何截取一段字符中,某一个字符的前面和后面的字符

    比如这里的1992631934@qq.com如何获取到@前面的1992631934和@后面的qq.com js代码如下: var mail="1992631934@qq.com" ...