老男孩14期自动化运维day8随笔和作业(多用户在线的轻量级ftpserver)

1.ftp server 的运行流程:
(1)读取客户端发过来的文件名
(2)检测文件是否存在
(3)打开文件
(4)检测文件大小
(5)发送文件大小和md5给客户端
(6)等待客户端确认
(7)开始边读边发
(8)发送md5

2.粘包问题
什么是粘包:两条send 挨着 容易被当成一条send (linux 上这种问题比较明显 )

3.socketserver(实现多个请求并发)
(1)你必须自己创建一个请求处理类,并且这个类要继承BaseRequestHandler,并且重写父类里的handle()方法
(2)你必须实例化一个TCPServer,并且传递serverip和你刚创建的请求处理类给这个TCPServer
(3)上面实例化的server,server.handle_request() # 只处理一个请求(用的少)
server.serve_forever() # 处理多个请求,永远执行,直到shut down。

0.0.0.0 是无论哪个ip地址都可以连上 有些时候一个主机可以有多个网卡,一个网卡对应一个或多个ip,所以会有多个ip
以下为多并发socketserver 基本写法:

import socketserver


# 多并发socketserver基本写法
class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):# 跟客户端每个请求都在handle 父类里handle() 为空

        while True:
            try:
                self.data=self.request.recv(1024).strip() # 必须要是self.request
                print("{} wrote:".format(self.client_address[0]))
                print(self.data)
                # if not self.data: # 客户端断了之后  python2.x 是断开没有异常的 3.x有自带的异常 要抓住
                #     print(self.client_address,"断开了")
                #     break
                self.request.send(self.data.upper())
            except ConnectionError as e:
                print(e)
                break


if __name__=='__main__':
    HOST,PORT="localhost",9999
    # 多并发
    server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler) # 多线程处理请求
    # server=socketserver.ForkingTCPServer((HOST,PORT),MyTCPHandler) 多进程处理请求, windows用不了

    # 单个请求
    # server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) 简化版单个请求

    server.serve_forever()

4.基于socket的减半ssh server
sock_server_ssh.py
注意有个坑:要获得传输数据的字节数 ,一个中文3个字节,一个英文1个字节,比如带有中文的string a,send 要这样写 send( str ( len(a.encode) ).encode()。因为第一个a.encode 是把字符串转换为byte 再len(byte)得到字节大小(为整数),整数不能直接encode,必须先转换为字符串再encode()。

#!/usr/bin/env python
# coding:utf-8
# Author:Yang
# 减半ssh

import socket,os
server=socket.socket()
server.bind(('localhost',9999))
server.listen()

while True:
    conn,addr=server.accept()
    print("new conn",addr)
    while True:
        print("等待连接")
        data=conn.recv(1024)
        if not data:
            print("客户端已断开...")
            break
        print("执行指令",data)
        cmd_res=os.popen(data.decode()).read() # 接收字符串 执行结果也是字符串
        print("before send",len(cmd_res))
        if len(cmd_res)==0:
            cmd_res="cmd has no output..."
        conn.send(str(len(cmd_res.encode())).encode("utf-8"))  # lenth 是整数 不能直接encode 所以要先str 在encode
        # 这是一个坑:注意上面len(cmd_res.encode()) 因为len("中")为1,必须要再encode才能获得字节数 ,一个中文三个字节!!
        # time.sleep(0.5)
        client_ack=conn.recv(1024) # wit client to confirm  这个方法用来防止socket粘包

        conn.send(cmd_res.encode("utf-8"))

server.close

sock_client_ssh.py

#!/usr/bin/env python
# coding:utf-8
# Author:Yang

import  socket

client=socket.socket()
client.connect(("localhost",9999))

while True:
    cmd = input(">>:").strip()
    if len(cmd)==0:
        continue

    client.send(cmd.encode("utf-8"))

    cmd_res_size = client.recv(1024) # 接收命令结果的长度
    print("命令结果大小",cmd_res_size)
    client.send("准备好接受了".encode("utf-8"))
    received_size=0
    received_data=b''
    while received_size < int(cmd_res_size.decode()):
        data=client.recv(1024)
        received_size+=len(data) # 每次收到的有可能小于1024 所以必须用len判断
        received_data+=data
        print(received_size)
        ##print(data.decode())
    else:
        print("cmd res receive done...",received_size)
        print(received_data.decode())
    # cmd_res=client.recv(1024)
    # print(cmd_res.decode())

client.close

5.作业:多用户在线的轻量级ftp server实现
功能:1.用户加密认证
2.允许多用户同时登陆
3.每个用户都有自己的家目录,且只能访问家目录(权限控制)
4.允许用户在ftp server 上切换目录
6.允许用户查看当前下目录的文件
7.支持上传、下载,保证文件一致性
8.文件传输过程显示进度条
未实现:磁盘配额,断点续传

github:https://github.com/yyyhhhrrr/ftpserver

猜你喜欢

转载自blog.csdn.net/qq_33060225/article/details/84136541