11-IO多路复用-paramiko-MySQL

Posted 汉克书

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了11-IO多路复用-paramiko-MySQL相关的知识,希望对你有一定的参考价值。


1. IO多路复用
2. paramiko
3. mysql
- SQL语句
- Python操作MySQL - pymysql模块



今日内容:
1. IO多路复用
- 监听多个socket变化


- socket服务端
IO多路复用 + socket 来实现Web服务器
a. 服务端优先运行
b. 浏览器: http://......
socket + send(\'协议..\')
c. 获取客户端发来的url,根据URL不同响应数据
d. 断开链接
产出:
a. 浏览器发送数据:按照指定规则
b. 监听多个socket对象
c.
Web框架开发者
业务开发者
d. 模块独立化
#!/usr/bin/env python
# _*_ coding:utf-8 _*_

import select
import socket
sock = socket.socket()
sock.setblocking(False)
sock.bind((\'127.0.0.1\',8888))
sock.listen(5)

def process_data(client):
    data = bytes()
    while True:
        try:
            chunk = client.recv(1024)
        except Exception as e:
            chunk = None
        if not chunk:
            break
        data += chunk
        data_str = str(data,encoding=\'utf-8\')
        header,body = data_str.split(\'\\r\\n\\r\\n\', 1)
        header_list = header.split(\'\\r\\n\')
        header_dick = {}
        for line in header_list:
            value = line.split(":",1)
            if len(value) == 2:
                k,v = value
                header_dick[k] = v
            else:
                header_dick[\'method\'],header_dick[\'url\'],header_dick[\'protocal\'] = line.split(\' \')
        return header_dick,body
inputs = [sock,]
while True:
    rlist,wlist,elist = select.select(inputs,[],[],0.05)
    for client in rlist:
        if client == sock:
            conn,addr = client.accept()
            conn.setblocking(False)
            inputs.append(conn)
        else:
            header_dicy,body = process_data(client)
            print(header_dicy)
            request_url = header_dicy[\'url\']
            client.sendall(request_url.encode(\'utf-8\'))
            inputs.remove(client)
            client.close()
http服务-函数
import select
import socket

class Http_server(object):
    def __init__(self,routers):
        self.routers = routers

    def process_data(self,conn):
        data = bytes()
        while True:
            try:
                chunk = conn.recv(1024)
            except Exception as e:
                chunk = None
            if not chunk:
                break
            data = data + chunk
        data_str = str(data, encoding=\'utf-8\')
        header, body = data_str.split(\'\\r\\n\\r\\n\', 1)
        header_list = header.split(\'\\r\\n\')

        header_dict = {}
        for line in header_list:
            value = line.split(\':\', 1)
            if len(value) == 2:
                k, v = value
                header_dict[k] = v
            else:
                header_dict[\'method\'], header_dict[\'url\'], header_dict[\'protcol\'] = line.split(\' \')
        return header_dict, body

    def run(self,host=\'127.0.0.1\',port=8888):
        sock = socket.socket()
        # sock.setblocking(False)
        sock.bind((host,port,))
        sock.listen(5)
        # while True:
        #     conn,addr = sock.accept() # 不在hang主,直接报错
        #     conn.setblocking(False)
        #     conn.recv(100)            # 不在hang主,直接报错
        inputs = [sock,]
        while True:
            # [1,]
            rList,wList,eList = select.select(inputs,[],[],0.5)
            for client in rList:
                # 建立连接
                if client == sock:
                    conn,addr = client.accept()
                    # conn.setblocking(False)
                    inputs.append(conn)
                else:
                    header_dict,body = self.process_data(client)
                    # client.recv(1024)
                    request_url = header_dict[\'url\']
                    # routers = [
                    #     (\'/index.html\', f1),
                    #     (\'/login.html\', f2)
                    # ]
                    func_name = None
                    for item in self.routers:
                        if item[0] == request_url:
                            func_name = item[1]
                            break
                    if not func_name:
                        client.sendall(b\'404\')
                    else:
                        result = func_name(header_dict,body)
                        client.sendall(result.encode(\'utf-8\'))
                    inputs.remove(client)
                    client.close()
http服务-类

import Http

def f1(header_dict,body):
    # ... Http...
    # .....
    return \'ffffff\'

def f2(header_dict,body):
    return \'aaaaaaaaaa\'

routers = [
    (\'/index.html\',f1),
    (\'/login.html\',f2)
]

obj = Http.Http_server(routers)
obj.run()
http服务-类
 
 
         参考博客:http://www.cnblogs.com/wupeiqi/p/6536518.html
- socket客户端(爬虫)
利用一个线程,同时发送n个请求(异步非阻塞模块)

url_list [
http://www.baidu.com,
http://www.baidu1.com,
http://www.baidu2.com,
http://www.baidu3.com,

]
import tornado.ioloop
import tornado.web


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")


application = tornado.web.Application([
    (r"/index.html", MainHandler),
])

if __name__ == "__main__":
    application.listen(8889)
    tornado.ioloop.IOLoop.instance().start()
程序员使用框架

a. 循环列表,为每一个URL生成Socket对象
b. 每一个socket对象,向远程发送链接请求
connect: 阻塞
c. 如果连接:
发送数据:遵循格式
d. 获取响应内容
e. 关闭

注意:可读和可写状态
import tornado.ioloop
import tornado.web
import socket
import select
sock = socket.socket()
sock.fileno()
class Foo(object):
    def __init__(self,sock,callback,url,host):
        self.sock = sock
        self.callback = callback
        self.url = url
        self.host = host

    def fileno(self):
        return self.sock.fileno()

class NbIO(object):

    def __init__(self):
        self.fds = []
        self.connections = []

    def connect(self,url_list):
        for item in url_list:
            conn = socket.socket()
            conn.setblocking(False)
            # 1. 发送链接请求
            try:
                conn.connect((item[\'host\'],80))
            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:
            # wList,有对象;当前socket已经创建链接
            try:
                if len(self.fds) == 0:
                    return
                rList,wList,eList = select.select(self.fds,self.connections,[],0.5)
                # 【1,11】
                for obj in rList:
                    # 4.有数据响应回来了
                    conn = obj.sock
                    data = bytes()
                    while True:
                        try:
                            d = conn.recv(1024)
                            data = data + d
                        except BlockingIOError as e:
                            d = None
                        if not d:
                            break
                    # print(data)
                    obj.callback(data) # 自定义操作 f1  f2
                    self.fds.remove(obj)
                    # print(len(self.fds),len(self.connections))
                    # 执行当前请求 函数:f1  f2
                # 【1,2,3,】
                for obj in wList:
                    # 2.已经连接上远程
                    conn = obj.sock
                    # 3. 发送数据
                    # HTTP/1.0\\r\\nHost: %s\\r\\n\\r\\n
                    template = "GET %s HTTP/1.1\\r\\nHost: %s\\r\\n\\r\\n" %(obj.url,obj.host,)

                    # template = "POST %s HTTP/1.1\\r\\nHost: 127.0.0.1:8888\\r\\n\\r\\nk1=v1&k2=v2" %(obj.url,)
                    conn.sendall(template.encode(\'utf-8\'))
                    self.connections.remove(obj)
            except OSError as e:
                pass    # 因为win下的select里的列表空了之后会报错,报错就忽视它

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")


application = tornado.web.Application([
    (r"/index.html", MainHandler),
])

if __name__ == "__main__":
    application.listen(8889)
    tornado.ioloop.IOLoop.instance().start()
异步IO模块

参考博客:http://www.cnblogs.com/wupeiqi/articles/6229292.html

产出:
1. setblockint(False)
2. select监听其他对象: def fileno():...
3. gevent,twisted,asycio ---> 单线程并发发送Http请求

2. Paramiko
参考博客:http://www.cnblogs.com/wupeiqi/articles/5095821.html
- 是一个模块,socket,SSH
- Python代码,实现远程服务器操作

功能:
a. 使用用户名密码:
- 命令 SSHClient -> Transport
- 文件 Transport
b. 使用用户名秘钥:
- 命令 SSHClient -> Transport
- 路径,也支持字符串形式
- 文件 Transport

====> SSH帮助类 <====
c.
执行创建session # 堡垒机 Bug
import paramiko

# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname=\'192.168.12.59\', port=22, username=\'root\', password=\'sungaohui1990\')

# 执行命令
stdin, stdout, stderr = ssh.exec_command(\'ls /\')
# 获取命令结果
result = stdout.read()
print(result)

# 关闭连接
ssh.close()
paramiko使用

import paramiko

class SshHelper(object):

    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,local,target):
        sftp = paramiko.SFTPClient.from_transport(self.transport)
        # 将location.py 上传至服务器 /tmp/test.py
        sftp.put(local, target)
        # 将remove_path 下载到本地 local_path
        # sftp.get(\'remove_path\', \'local_path\')

    def cmd(self,shell):
        ssh = paramiko.SSHClient()
        ssh._transport = self.transport
        stdin, stdout, stderr = ssh.exec_command(shell)
        stdout.read()

    def close(self):
        self.transport.close()

if __name__ == \'__main__\':

    obj = SshHelper(\'10.0.0.61\',\'22\',\'root\',\'123456\')
    obj.connect()
    obj.close()
paramikoHelper
        产出:
- 链接远程,操作:命令,文件


3. MySQL
- 什么是MySQL
服务端:
a.socket服务端运行,监听:IP和端口
b.获取客户端发送的数据:
c.解析
d.去文件中做操作
客户端:
a.socket客户端:基于各种语言的客户端
b.验证
c.发送命令(学习规则SQL语句)
- 安装
服务端:
客户端:

- 基本使用:
a. 申请
用户:

授权:
用户名,数据库(文件夹),表(文件),增删改查,IP

b. 连接
 mysql -u root -h c1.com -p
 asdfasdf


 mysql -u wupeiqi -h 192.168.12.111 -p 123


c. 规则
文件夹(数据库):
 create database db1 default charset utf8;
 drop database db1;

 show databases;
 use db1;


文件(表):
    show tables;


    create table tb1(
        id int not null auto_increment primary key,
        name char(20) null default 1,
        age int not null)engine=innodb default charset utf8;


    # 增
    insert into tb1(name,age) values(\'alex\',18);
    # 删
    delete from tb1 where id>1;
    # 改
    update tb1 set age=168 where id=2;
    # 查
    select * from tb1;
     

============================================================

外键:foreign key 一对多
    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)
    )


双向的外键: 多对多
    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)
    )


连表:
    select * from person;

    select * from person
    left join deparment on person.deparment_id = deparment.id
    # 
    1   alex   18  1  1  咨询
    2   oldboy 68  3  3  基础


    select id from deparment where title = "基础"

    select hostid from host_deparment where deparment_id=1111

    select * from host id in (1,2,3)

    ####### 




4. pymysql
pip3 install pymysql

# 内部socket
import pymysql

conn = pymysql.connect(host=\'127.0.0.1\', port=3306, user=\'root\', passwd=\'\', db=\'host_manage\')
# cursor = conn.cursor()
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行SQL,并返回受影响行数#  被搞...
effect_row = cursor.execute("select * from user",)
conn.commit()
ret = cursor.fetchall()
# ret = cursor.fetchmany(3)
# ret = cursor.fetchone()
# print(ret)
# ret = cursor.fetchone()
# print(ret)
cursor.close()
conn.close()

print(ret)
pymysql使用

        import pymysql

        # 创建连接
        conn = pymysql.connect(host=\'127.0.0.1\', port=3306, user=\'root\', passwd=\'123\', db=\'t1\')
        # 创建游标
        cursor = conn.cursor()

        username = input(\'请输入用户名:\')
        pwd =  input(\'请输入密码:\')

        # 执行SQL,并返回受影响行数
        #effect_row = cursor.execute("select * from userinfo where username=%s and pwd = %s", (username,pwd,))

        # root or 1==1 -- 
        # adfasdf
        # sql =  "select * from userinfo where username=%s and pwd = %s" %(username,pwd,)
        # select * from userinfo where username=root or 1==1 --  and pwd = %s
        #effect_row = cursor.execute(sql)

        # 提交,不然无法保存新建或者修改的数据
        conn.commit()

        # 关闭游标
        cursor.close()
        # 关闭连接
        conn.close()
pymysql使用

以上是关于11-IO多路复用-paramiko-MySQL的主要内容,如果未能解决你的问题,请参考以下文章

计算机网络6--多路复用技术

多路复用技术

TCP的多路复用和分解

NIO和IO多路复用

多路复用技术

非阻塞套接字与IO多路复用