学习python_day10

io多路复用的封装服务端

模块名:panglicai

import socket
import select
class Panglicai(object):
    def __init__(self,routers):
        self.routers = routers
    def process_data(self,conn):
        data = bytes()
        while True:
            try:
                chunk = conn.recv(4096)
            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_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["protal"]=line.split(" ")
        return header_dict ,body

    def run(self,host="127.0.0.1",port = 8888):
        sk= socket.socket()
        sk.setblocking(False)
        sk.bind((host,port))
        sk.listen(5)
        inputs = [sk,]
        while True:
            try:
                r,w,e = select.select(inputs,[],[],0.5)
                for client in r:
                    if client ==sk:
                        conn,addr = client.accept()
                        inputs.append(conn)
                        conn.setblocking(False)
                    else:
                        header_dict,body = self.process_data(client)
                        reuest_url=header_dict["url"]
                        # routers = [
                        #     ('/index.html', f1),
                        #     ('/login.html', f2)
                        # ]
                        func_name = None
                        for item in self.routers:
                            if item[0]==reuest_url:
                                func_name =item[1]
                                break
                        if not func_name:
                            client.sendall(b"404")
                        else:
                            reslut = func_name(header_dict,body)
                            client.sendall(reslut.encode())
                        inputs.remove(client)
                        client.close()
            except OSError as e:
                pass

导入模块

import panglicai
def f1(header_dict,body):
    return  "beautiful!"
def f2(header_dict,body):
    return "漂亮!"

routers = [
    ("/index.html",f1),
    ("/login.html",f2),
]
obj = panglicai.Panglicai(routers)
obj.run()

socket客户端:利用一个线程,同时发送n个请求(异步非阻塞模块)
实现过程:循环列表,为每个url生成一个socket对象

url = [http://www.baidu.com,http://cnblogs.com,]每个socket对象向远程发送链接请求,如果链接成功,发送数据(遵循http协议格式),获取响应内容,关闭链接

注意:当socket对象发送链接请求时,是等待服务端响应,这时socket对象是可读的(读服务端返回允许链接),等读到服务端响应允许连接时,表示已经链接成功了,

链接成功后,socket对象就变成可写了,就是发送数据,发送完数据就变为可读状态了,是为了等待接受服务端返回的数据了,(等待接受服务端响应是可读,自己发送数据是可写)。

1、单独的一个知识点

import select
import socket
sk = socket.socket()
sk.bind(("127.0.0.1",8888))
sk.listen(5)
inputs = [sk,]
# class Foo(object):
#     def __init__(self,name):
#         self.sk = socket.socket()
#         self.name = name
#     def fileno(self):
#         return self.sk.fileno()
while True:
    r,w,e = select.select(inputs,[],[],0.5)#inputs 就是[sk,]
    #select模块监听的就是[sk,]列表,他内部会自动调用fileno方法实现监听的(socket对象内部有个fileno方法)
    #所以[sk,]列表中个放其他的对象只要按照规则就行,我们就可以封装socket对象了
    #r,w,e = select.select([Foo(),[],[],0.5])这样就可以把socket对象封装在Foo()中了,又可以添加新的功能(Foo().name )
    # 因此[]列表中添加的对象只要能自动执行fileno方法调用出socket对象的fileno方法就行,

 也把客户端做成模块化,模块名:iomodle

import select
import socket
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.connetions = []
    def request(self,url_list):
        for item in url_list:
            conn=socket.socket()
            conn.setblocking(False)#不等待上个连接同时发送url_list中的所有请求连接,不加会等待一个连接成功后再发送下个连接
            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.connetions.append(obj)
    def send(self):#连接成功后监听conn的变化
        while True:
            try:
                if len(self.fds) == 0:#等于0时说明都返回了数据处理完了
                    return
                #w:代表可写,如果w有对象就代表连接成功了
                r,w,e = select.select(self.fds,self.connetions,self.fds,0.5)
                for obj in r:
                    conn = obj.sock
                    data =bytes()
                    while True:
                        try:
                            d = conn.recv(1024)
                            data+=d

                        except BlockingIOError as e:
                            d = None
                        if not d:
                            break
                    obj.callback(data)
                    self.fds.remove(obj)

                for obj in w:
                    conn = obj.sock
                    templet = "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n" %(obj.url,obj.host,)
                    conn.send(templet.encode())
                    self.connetions.remove(obj)
            except OSError as e:#OSError 是系统问题在linux和mac上不会报这个错(是当监听的r w都为空时Windows会报错)
                pass

 

导入模块使用

"""
socket客户端同时发送多个请求,收到响应后根据不同的请求调用不同的函数处理
"""
import iomodle
def f1(data):
    print(data)
def f2(data):
    print(data)

url_list =[
    {"host":"www.baidu.com","url":"/","callback":f1},
    {"host":"www.cnblogs.com","url":"/plc-python","callback":f2},
    {"host":"www.bing.com","url":"/","callback":f1},
    ]

panglicai = iomodle.Nbio()
panglicai.request(url_list)
panglicai.send()

 paramiko,第三方模块,内部封装了socket 可以根据ssh协议发送数据和接受数据

导入模块,用python代码实现远程服务的操作

SSHClient

基于用户名密码连接:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import paramiko
  
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', password='123')
  
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
  
# 关闭连接
ssh.close()

 SSHClient内部其实也是调用的transport

import paramiko

transport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', password='123')

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()

transport.close()
sshclient封装transport

基于公钥密钥连接:

import paramiko
 
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
 
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', key=private_key)
 
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
result = stdout.read()
 
# 关闭连接
ssh.close()
import paramiko

private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')

transport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', pkey=private_key)

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')

transport.close()
SSHClient封装transport
import paramiko
from io import StringIO

key_str = """-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAq7gLsqYArAFco02/55IgNg0r7NXOtEM3qXpb/dabJ5Uyky/8
NEHhFiQ7deHIRIuTW5Zb0kD6h6EBbVlUMBmwJrC2oSzySLU1w+ZNfH0PE6W6fans
H80whhuc/YgP+fjiO+VR/gFcqib8Rll5UfYzf5H8uuOnDeIXGCVgyHQSmt8if1+e
7hn1MVO1Lrm9Fco8ABI7dyv8/ZEwoSfh2C9rGYgA58LT1FkBRkOePbHD43xNfAYC
tfLvz6LErMnwdOW4sNMEWWAWv1fsTB35PAm5CazfKzmam9n5IQXhmUNcNvmaZtvP
c4f4g59mdsaWNtNaY96UjOfx83Om86gmdkKcnwIDAQABAoIBAQCnDBGFJuv8aA7A
ZkBLe+GN815JtOyye7lIS1n2I7En3oImoUWNaJEYwwJ8+LmjxMwDCtAkR0XwbvY+
c+nsKPEtkjb3sAu6I148RmwWsGncSRqUaJrljOypaW9dS+GO4Ujjz3/lw1lrxSUh
IqVc0E7kyRW8kP3QCaNBwArYteHreZFFp6XmtKMtXaEA3saJYILxaaXlYkoRi4k8
S2/K8aw3ZMR4tDCOfB4o47JaeiA/e185RK3A+mLn9xTDhTdZqTQpv17/YRPcgmwz
zu30fhVXQT/SuI0sO+bzCO4YGoEwoBX718AWhdLJFoFq1B7k2ZEzXTAtjEXQEWm6
01ndU/jhAasdfasdasdfasdfa3eraszxqwefasdfadasdffsFIfAsjQb4HdkmHuC
OeJrJOd+CYvdEeqJJNnF6AbHyYHIECkj0Qq1kEfLOEsqzd5nDbtkKBte6M1trbjl
HtJ2Yb8w6o/q/6Sbj7wf/cW3LIYEdeVCjScozVcQ9R83ea05J+QOAr4nAoGBAMaq
UzLJfLNWZ5Qosmir2oHStFlZpxspax/ln7DlWLW4wPB4YJalSVovF2Buo8hr8X65
lnPiE41M+G0Z7icEXiFyDBFDCtzx0x/RmaBokLathrFtI81UCx4gQPLaSVNMlvQA
539GsubSrO4LpHRNGg/weZ6EqQOXvHvkUkm2bDDJAoGATytFNxen6GtC0ZT3SRQM
WYfasdf3xbtuykmnluiofasd2sfmjnljkt7khghmghdasSDFGQfgaFoKfaawoYeH
C2XasVUsVviBn8kPSLSVBPX4JUfQmA6h8HsajeVahxN1U9e0nYJ0sYDQFUMTS2t8
RT57+WK/0ONwTWHdu+KnaJECgYEAid/ta8LQC3p82iNAZkpWlGDSD2yb/8rH8NQg
9tjEryFwrbMtfX9qn+8srx06B796U3OjifstjJQNmVI0qNlsJpQK8fPwVxRxbJS/
pMbNICrf3sUa4sZgDOFfkeuSlgACh4cVIozDXlR59Z8Y3CoiW0uObEgvMDIfenAj
98pl3ZkCgYEAj/UCSni0dwX4pnKNPm6LUgiS7QvIgM3H9piyt8aipQuzBi5LUKWw
DlQC4Zb73nHgdREtQYYXTu7p27Bl0Gizz1sW2eSgxFU8eTh+ucfVwOXKAXKU5SeI
+MbuBfUYQ4if2N/BXn47+/ecf3A4KgB37Le5SbLDddwCNxGlBzbpBa0=
-----END RSA PRIVATE KEY-----"""

private_key = paramiko.RSAKey(file_obj=StringIO(key_str))
transport = paramiko.Transport(('10.0.1.40', 22))
transport.connect(username='wupeiqi', pkey=private_key)

ssh = paramiko.SSHClient()
ssh._transport = transport

stdin, stdout, stderr = ssh.exec_command('df')
result = stdout.read()

transport.close()

print(result)
基于私钥字符串

SFTPClient

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

基于用户名密码上传下载

import paramiko
 
transport = paramiko.Transport(('hostname',22))
transport.connect(username='wupeiqi',password='123')
 
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
 
transport.close()
基于公钥密钥上传下载
import paramiko
 
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
 
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', pkey=private_key )
 
sftp = paramiko.SFTPClient.from_transport(transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 将remove_path 下载到本地 local_path
sftp.get('remove_path', 'local_path')
 
transport.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)
        res=stdout.read()
        print(res)

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

if __name__ == '__main__':

    obj = SshHelper('192.168.3.65',22,"root","redhat")
    obj.connect()
    obj.cmd("ls")
    obj.upload("C:/Users/panglc/PycharmProjects/day1/day10/panglicai.py","/tmp/test.py")
    #....可以执行多次
    obj.close()

 

 

 

 

posted @ 2017-03-28 15:49  python-残阳  阅读(392)  评论(0)    收藏  举报