人生苦短,我用python-- Day8

目录                          

  动态导入模块

  断言

  socket高级编程

  socketServer

动态导入模块                                

先看一下目录结构

动态导入模块有两种方式,我们先来看第一种:

# Author:Sean sir
# 这种情况下导入的是lib目录,如果想调用lib目录下的aa模块,需要在继续往下调用
mod = __import__('lib.aa') obj = mod.aa.C() print(obj.name)

我们来看第二种方法:

# Author:Sean sir
# 这种情况下导入的直接是aa模块,如果想用aa模块里面的方法,直接调用就可以了。
import importlib mod = importlib.import_module('lib.aa') obj = mod.C() print(obj.name)

 断言                                  

关键字:assert

作用:提高逼格,在操作后面代码前先进行判断。与if进行判断相差无几

代码:

# Author:Sean sir
user_input = input('>>>:')
assert type(user_input) is str
print('aaa')

# 输出
>>>:asdf
aaa

socket高级编程                                

写一个ssh的工具

# Author:Sean
import socket,os
server = socket.socket()
server.bind(('127.0.0.1',8888))
server.listen()
while True:
    print('我要开始等电话了')
    conn,add = server.accept()
    while True:
        print('电话来了')
        data = conn.recv(1024)
        if not len(data):break
        data = data.decode('utf-8')
        print(type(data))
        cmd_str = os.popen(data).read()
        len_cmd_str = str(len(cmd_str)).encode('utf-8')
        conn.send(len_cmd_str)
        conn.send(cmd_str.encode('utf-8'))
    server.close()
ssh server
# Author:Sean sir
import socket
client = socket.socket()
client.connect(('127.0.0.1',8888))
while True:
    user_input = input('>>:').strip()
    if not len(user_input):
        continue
    client.send(user_input.encode('utf-8'))
    data_1 = int(client.recv(1024).decode('utf-8'))
    recv_size = 0
    recv = b''
    while recv_size != data_1:
        recv_data = client.recv(1024)
        recv_size += len(recv_data)
        recv += recv_data
    else:
        print(recv.decode('utf-8'))
        print('收取执行命令结果完成!')
client.close()
ssh client

上面的server如果两条send命令在一起,那么会出现粘包的问题,粘包:就是说系统会把两个包同时当做一个包的数据发送过去,解决上述问题,继续看代码:

 其实很简单,只需要在两个send中间加一个sleep时间就可以了。

# Author:Sean
import socket,os,time
server = socket.socket()
server.bind(('127.0.0.1',8888))
server.listen()
while True:
    print('我要开始等电话了')
    conn,add = server.accept()
    while True:
        print('电话来了')
        data = conn.recv(1024)
        if not len(data):break
        data = data.decode('utf-8')
        print(data)
        cmd_str = os.popen(data).read()
        len_cmd_str = str(len(cmd_str)).encode('utf-8')
        conn.send(len_cmd_str)
        time.sleep(0.5)
        conn.send(cmd_str.encode('utf-8'))
    server.close()
ssh server
# Author:Sean sir
import socket
client = socket.socket()
client.connect(('127.0.0.1',8888))
while True:
    user_input = input('>>:').strip()
    if not len(user_input):
        continue
    client.send(user_input.encode('utf-8'))
    data_1 = int(client.recv(1024).decode('utf-8'))
    recv_size = 0
    recv = b''
    while recv_size != data_1:
        recv_data = client.recv(1024).decode('utf-8')
        recv_size += len(recv_data)
        # recv += recv_data
        print(recv_data)
    else:
        print(recv.decode('utf-8'))
        print('收取执行命令结果完成!')
client.close()
ssh client

 上面的实现形式有没有感觉到low啊,不能时时的返回数据,我们来一个高大上的解决办法

 解决思路大概是: 当我发送了执行结果大小后,然后在接受一个客户端发送过来的确认包,如果接受到了,那么继续发送执行结果,如果没有接收到那么就等待,

 这里就不会出现粘包的问题了。

# Author:Sean
import socket,os,time
server = socket.socket()
server.bind(('127.0.0.1',7777))
server.listen()
while True:
    print('我要开始等电话了')
    conn,add = server.accept()
    while True:
        print('电话来了')
        data = conn.recv(1024)
        if not len(data):break
        data = data.decode('utf-8')
        print(data)
        cmd_str = os.popen(data).read()
        len_cmd_str = str(len(cmd_str)).encode('utf-8')
        conn.send(len_cmd_str)
        #time.sleep(0.5)
        ack = conn.recv(1024)
        print(ack)
        conn.send(cmd_str.encode('utf-8'))
    server.close()
ssh server
# Author:Sean sir
import socket
client = socket.socket()
client.connect(('127.0.0.1',7777))
while True:
    user_input = input('>>:').strip()
    if not len(user_input):
        continue
    client.send(user_input.encode('utf-8'))
    data_1 = int(client.recv(1024).decode('utf-8'))
    client.send('我已经做好接受命令准备了!loser发送命令吧!'.encode('utf-8'))
    recv_size = 0
    recv = b''
    while recv_size != data_1:
        recv_data = client.recv(1024).decode('utf-8')
        recv_size += len(recv_data)
        # recv += recv_data
        print(recv_data)
    else:
        print(recv.decode('utf-8'))
        print('收取执行命令结果完成!')
client.close()
ssh client

写一个ftp的工具

# Author:Sean
import socket,os,hashlib
server = socket.socket()
server.bind(('127.0.0.1',7777))
server.listen()
while True:
    print('等待新的客户端连接')
    conn,add = server.accept()
    while True:
        print('等待新指令:')
        data = conn.recv(1024)
        if not len(data):
            print('客户端已断开。。。。。')
            break
        cmd,filename = data.decode().split()
        # print(filename)
        if os.path.isfile(filename):
            f = open(filename,'rb')
            m = hashlib.md5()
            file_size = os.stat(filename).st_size
            conn.send(str(file_size).encode())  # 发送一个文件大小到客户端
            # print(str(file_size))
            ack_info = conn.recv(1024) # 等待客户端发送收到确认信息
            for line in f:
                conn.send(line)
            f.close()
    server.close()
ftp server
# Author:Sean sir
import socket
client = socket.socket()
client.connect(('127.0.0.1',7777))
while True:
    user_input = input('>>:').strip()
    if not len(user_input):continue
    if user_input.startswith('get'):
        client.send(user_input.encode())
        server_response = client.recv(1024)
        print('Server response:',server_response)
        client.send(b'ready to recv file!')
        file_total_size = int(server_response.decode())
        received_size = 0
        filename = user_input.split()[1]
        f = open(filename+'_new','wb')
        while received_size < file_total_size:
            data = client.recv(1024)
            received_size += len(data)
            f.write(data)
            print(received_size,file_total_size)
        else:
            print('file recv done')
            f.close()
client.close()
ftp client

优化上面的ftp,给上面的ftp传输后的文件md5下,查看下两个文件md5是否一致,最后发送md5的时候,可能会出现粘包的问题,在客户端我们稍微做了处理,当接受的剩余文件小于1024时候的,最后只收文件总大小减去接受到的文件大小的字节数。

# Author:Sean
import socket,os,hashlib
server = socket.socket()
server.bind(('127.0.0.1',7777))
server.listen()
while True:
    print('等待新的客户端连接')
    conn,add = server.accept()
    while True:
        print('等待新指令:')
        data = conn.recv(1024)
        if not len(data):
            print('客户端已断开。。。。。')
            break
        cmd,filename = data.decode().split()
        # print(filename)
        if os.path.isfile(filename):
            f = open(filename,'rb')
            m = hashlib.md5()
            file_size = os.stat(filename).st_size
            conn.send(str(file_size).encode())  # 发送一个文件大小到客户端
            # print(str(file_size))
            ack_info = conn.recv(1024) # 等待客户端发送收到确认信息
            for line in f:
                m.update(line) # 哈希这一行文件
                conn.send(line)
            f.close()
            conn.send(m.hexdigest().encode())
    server.close()
ftp server
# Author:Sean sir
import socket,hashlib
client = socket.socket()
client.connect(('127.0.0.1',7777))
while True:
    user_input = input('>>:').strip()
    if not len(user_input):continue
    if user_input.startswith('get'):
        client.send(user_input.encode())
        server_response = client.recv(1024)
        print('Server response:',server_response.decode())
        client.send(b'ready to recv file!')
        file_total_size = int(server_response.decode())
        received_size = 0
        filename = user_input.split()[1]
        f = open(filename+'_new','wb')
        m = hashlib.md5()
        while received_size < file_total_size:
            if file_total_size - received_size < 1024:
                size = file_total_size - received_size
            else:
                size = 1024
            data = client.recv(size)
            m.update(data)
            received_size += len(data)
            f.write(data)
        else:
            print('文件接收完毕!')
            f.close()
        server_file_md5 = client.recv(1024)
        if server_file_md5.decode() == m.hexdigest():
            print('经过md5检验,两个文件完全相同!')
client.close()
ftp client

 SocketServer                              

不同于Socket的是,这个可以处理多个请求,socket只能处理单线程。

创建一个SocketServer大概分如下几步:

第一步:创建一个一个请求处理类,并且这个类要集成BaseRequestHandler,并且还要重写父类的handle()方法。

第二步:你必须实例化一个类,我们常用(TCPServer),并且传递server IP和你上面穿件的请求处理类给这个TCPServer

第三步:可以是用handle_request()或server_forever()进行处理请求,前者只处理一个请求,后者可以处理多个请求,永久执行

第四步:调用server_close()关闭socket

使用socketServer来简单实现以下socket编程,客户端输入数据,返回大写

# Author:Sean sir
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            self.data = self.request.recv(1024).strip()
            if not self.data :
                print('主机断开!')
                break
            print("{} wrote:".format(self.client_address[0]))
            print(self.data)
            self.request.sendall(self.data.upper())
if __name__ == "__main__":
    HOST, PORT = '127.0.0.1', 8888
    server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
    server.serve_forever()
socketServer_server
# Author:Sean sir
import socket
client = socket.socket()
client.connect(('127.0.0.1',8888))
while True:
    user_input = input('>>:').strip()
    if not len(user_input):
        continue
    client.send(user_input.encode('utf-8'))
    data = client.recv(1024)
    print(data.decode('utf-8'))
client.close()
socketServer_client

调皮的大王说,现在这种情况,依旧不能实现多线程,那就继续往下看,到底实现多线程!

 我们只需要把

server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)

换成

server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)

就可以了,就是这么简单,我也惊呆了!!!!

0

原文地址:https://www.cnblogs.com/xinzhiyu/p/5861229.html