利用python脚本制作ftp服务器

服务端

import socket
import argparse
import struct
import json
import os


def recvall(sock, length):
    data = b''
    while len(data) < length:
        more = sock.recv(length - len(data))
        if not more:
            raise Exception("peer closed.")
        data += more
    return data


def handle_dir_req(csock, req):
    # 1.获得文件清单
    res = os.listdir()
    res_bytes = json.dumps(res).encode()
    # 2.构造响应头
    head = {
        'status': 'ok',
        'content-length': len(res_bytes),
    }
    head_bytes = json.dumps(head).encode()
    # 3.构造响应头长度信息
    head_length = len(head_bytes)
    head_length_bytes = struct.pack('>i', head_length)
    # 4.发送3段数据
    csock.sendall(head_length_bytes)
    csock.sendall(head_bytes)
    csock.sendall(res_bytes)


def handle_get_req(csock, file):
    # res=os.read(req)
    # res_bytes = json.dumps(res).encode()
    res_bytes = open(file,"rb").read()
    # 2.构造响应头
    head = {
        'status': 'ok',
        'content-length': len(res_bytes),
        'file':file,
    }
    head_bytes = json.dumps(head).encode()
    head_length = len(head_bytes)
    head_length_bytes = struct.pack('>i', head_length)
    csock.sendall(head_length_bytes)
    csock.sendall(head_bytes)
    csock.sendall(res_bytes)

def handle_up_req(csock,res_head):
    res_data_length = res_head["content-length"]
    res_data_bytes = recvall(csock, res_data_length)
    open(res_head['name'], 'wb').write(res_data_bytes)
    # 2.构造响应头
    res='success!',
    res_bytes=json.dumps(res).encode()
    head = {
        'status': 'ok',
        'content-length': len(res_bytes),
    }
    head_bytes = json.dumps(head).encode()
    head_length = len(head_bytes)
    head_length_bytes = struct.pack('>i', head_length)
    csock.sendall(head_length_bytes)
    csock.sendall(head_bytes)
    csock.sendall(res_bytes)

def handle_dele_req(csock,req):
    os.remove(req)
    res = 'success!',
    res_bytes = json.dumps(res).encode()

    head = {
        'status': 'ok',
        'content-length': len(res_bytes),
    }
    head_bytes = json.dumps(head).encode()
    head_length = len(head_bytes)
    head_length_bytes = struct.pack('>i', head_length)
    csock.sendall(head_length_bytes)
    csock.sendall(head_bytes)
    csock.sendall(res_bytes)

def handel_exit_req(csock,req):
    name='success!'
    res_bytes = json.dumps(name).encode()
    # 2.构造响应头
    head = {
        'status': 'ok',
        'content-length': len(res_bytes),
    }
    head_bytes = json.dumps(head).encode()
    head_length = len(head_bytes)
    head_length_bytes = struct.pack('>i', head_length)
    csock.sendall(head_length_bytes)
    csock.sendall(head_bytes)
    csock.sendall(res_bytes)

mapping = {
    "dir": handle_dir_req,
    "get": handle_get_req,
    "upload": handle_up_req,
    "dele": handle_dele_req,
    "exit": handel_exit_req,
}


def serve_ftp_client(csock):
    while True:
        try:
            # 1.获得请求头,然后解析json格式,判断是get还是dir
            head_length_bytes = recvall(csock, 4)
            head_length = struct.unpack('>i', head_length_bytes)[0]

            req_bytes = recvall(csock, head_length)
            req = json.loads(req_bytes.decode())

            # 2.根据客户的请求去调用具体的子函数
            cmd = req.get("cmd")
            name=req.get("name")
            print(req)
            if cmd =='upload':
                handle_up_req(csock, req)
            else:
                function = mapping[cmd]
                function(csock, name)
        except Exception as e:
            break


def main(ip='0.0.0.0', port=21):
    # 1. 创建socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. bind
    sock.bind((ip, port))
    # 3. listen
    sock.listen(1)
    # 4. 进入循环accept
    while True:
        csock, caddr = sock.accept()
        # 5. 服务客户send/recv
        serve_ftp_client(csock)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="ftp server v0.1")
    parser.add_argument("--ip", default='0.0.0.0', help="ftp server ip, default=0.0.0.0")
    parser.add_argument("--port", type=int, default=21, help="ftp server port, default=21")
    args = parser.parse_args()
    main(args.ip, args.port)

客户端

# coding:utf8
import argparse
import json
import socket
import struct


def recvall(sock, length):
    data = b''
    while len(data) < length:
        more = sock.recv(length - len(data))
        if not more:
            raise Exception("peer closed.")
        data += more
    return data

def recv_responsed(sock):
    head_length_bytes = recvall(sock, 4)
    head_length = struct.unpack('>i', head_length_bytes)[0]
    req_head_bytes = recvall(sock, head_length)
    res_head = json.loads(req_head_bytes.decode())
    res_data_length = res_head["content-length"]
    res_data_bytes = recvall(sock, res_data_length)
    res = json.loads(res_data_bytes.decode())
    return res

def recv_response(sock):
    head_length_bytes = recvall(sock, 4)
    head_length = struct.unpack('>i', head_length_bytes)[0]
    req_head_bytes = recvall(sock, head_length)
    res_head = json.loads(req_head_bytes.decode())
    res_data_length = res_head["content-length"]
    res_data_bytes = recvall(sock, res_data_length)
    open(res_head['file'],'wb').write(res_data_bytes)
    return 'success!'


def main(ip, port):
    # 1. 创建socket
    csock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2. connect
    csock.connect((ip, port))
    # 3. input/send/recv
    while True:
        cmd = input("请输入您的命令(例:dir,get,upload,dele,exit):").strip()
        if cmd == 'dir':
            head = {'cmd': 'dir'}
            head_bytes = json.dumps(head).encode()
            head_length = len(head_bytes)
            head_length_bytes = struct.pack('>i', head_length)
            csock.sendall(head_length_bytes)
            csock.sendall(head_bytes)
            res = recv_responsed(csock)
            print(res)
        elif cmd == 'get':
                name= input("请输入文件名:").strip()

                head = {'cmd': 'get','name':name}
                head_bytes = json.dumps(head).encode()
                head_length = len(head_bytes)
                head_length_bytes = struct.pack('>i', head_length)
                csock.sendall(head_length_bytes)
                csock.sendall(head_bytes)
                res = recv_response(csock)
                print(res)

        elif cmd =='upload':
                file= input("请输入文件名:").strip()
                #res = os.stat(file)
                res_bytes = open(file, "rb").read()
                head = {
                    'cmd':'upload',
                    'status': 'ok',
                    'content-length': len(res_bytes),
                    'name': file,
                }
                head_bytes = json.dumps(head).encode()
                head_length = len(head_bytes)
                head_length_bytes = struct.pack('>i', head_length)
                csock.sendall(head_length_bytes)
                csock.sendall(head_bytes)
                csock.sendall(res_bytes)
                res = recv_responsed(csock)
                print(res)
        elif cmd == 'dele':
                name = input("请输入文件名:").strip()
                head = {'cmd': 'dele', 'name': name}
                head_bytes = json.dumps(head).encode()
                head_length = len(head_bytes)
                head_length_bytes = struct.pack('>i', head_length)
                csock.sendall(head_length_bytes)
                csock.sendall(head_bytes)

                res = recv_responsed(csock)
                print(res)
        elif cmd == 'exit':
            break





if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="ftp client v0.1")
    parser.add_argument("--ip", default='127.0.0.1', help="ftp server ip, default=127.0.0.1")
    parser.add_argument("--port", type=int, default=21, help="ftp server port, default=21")
    args = parser.parse_args()
    main(args.ip, args.port)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值