FTP程序

需求:开发一个支持多用户同时在线的FTP程序

要求:
1、用户加密认证
2、允许同时多用户登录(用到并发编程的知识,选做)
3、每个用户有自己的家目录,且只能访问自己的家目录
4、对用户进行磁盘配额,每个用户的可用空间不同(选做)
5、允许用户在ftp server上随意切换目录
6、允许用户查看当前目录下的文件
7、允许上传和下载文件,并保证文件的一致性
8、文件传输过程中显示进度条
9、附加:支持文件的断点续传(选做)
开发的程序需符合PEP8开发规范,及专业的生产软件设计规范,包括目录、代码命名、功能接口等



client

conf\settings

import os

BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DOWN_PATH = os.path.join(BASE_PATH, "download")
UP_PATH = os.path.join(BASE_PATH, "upload")

CODING = "utf-8"
MAX_PACKET_SIZE = 8192

client

import os
import sys
import socket
import struct
import json
import hashlib
import shelve

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from conf import settings

class MYClient:
    """
    ftp客户端
    """
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM

    def __init__(self, server_address):
        self.server_address = server_address
        self.socket = socket.socket(self.address_family, self.socket_type)
        self.client_connect()
        self.username = None
        self.client_status = False
        self.terimal = None
        self.shelve_obj = shelve.open("db")
        self.server_file_path = None
        self.home_path = None

    def client_connect(self):
        """与服务器连接"""
        self.socket.connect(self.server_address)

    def read_file(self, path):
        """读取文件"""
        with open(path, "rb") as f:
            return f.read()

    def hash_md5(self, msg):
        """加密"""
        m = hashlib.md5()
        m.update(msg)
        # print(m.hexdigest())
        return m.hexdigest()

    def header(self, status, **kwargs):
        """制作、发送报头"""
        header_dic = kwargs
        header_dic["status"] = status

        header_json = json.dumps(header_dic)
        header_bytes = header_json.encode(settings.CODING)
        self.socket.send(struct.pack("i", len(header_bytes)))    # header_dic的大小传送给客户端
        self.socket.send(header_bytes)                      # header_dic数据传送给客户端

    def recv_header(self):
        """接收报头"""
        header = self.socket.recv(4)      # 接收报头
        header_size = struct.unpack("i", header)[0]
        header_bytes = self.socket.recv(header_size)     # 接收报头信息
        header_json = header_bytes.decode(settings.CODING)
        header_dic = json.loads(header_json)
        return header_dic

    def get(self, data):
        """
        下载
        :param data: 指令、文件名、用户名
        :return:
        """
        if len(data) == 2:
            username = data[1]
            filename = input("请输入上传文件名:")
        else:
            username = data[2]
            filename = data[1]
        msg = {"action_type": "get", "filename": filename, "username": username, "s_file_path": self.server_file_path}
        self.socket.send(json.dumps(msg).encode(settings.CODING))

        header_dic = self.recv_header()
        if header_dic["status"] == "200":
            self.socket.send(header_dic["status"].encode(settings.CODING))
            c_file_path = os.path.join(os.path.join(settings.DOWN_PATH, msg["username"]), msg["filename"])
            self.server_file_path = header_dic["s_file_path"]
            long = str(len(self.shelve_obj.keys())+1)
            while True:
                if long in self.shelve_obj.keys():
                    long = str(int(long) + 1)
                else:
                    break
            if os.path.isfile(c_file_path):
                print("%s文件已存在" % filename)
                self.socket.send("000".encode(settings.CODING))
                return
            else:
                self.socket.send("999".encode(settings.CODING))

            self.shelve_obj[long] = {
                "filename": msg["filename"]+".download",
                "s_file_path": self.server_file_path+".download",
                "file_size": header_dic["file_size"]
            }

            with open("%s.download" % c_file_path, "wb")as f:     # 接收数据
                recv_size = 0
                while recv_size < header_dic["file_size"]:
                    line = self.socket.recv(settings.MAX_PACKET_SIZE)
                    f.write(line)
                    recv_size += len(line)

                    self.progress_bar(recv_size, header_dic["file_size"])

                f.close()
                os.rename("%s.download" % c_file_path, c_file_path)
                num = self.hash_md5(self.read_file(c_file_path))
                if num == header_dic["md5"]:
                    self.socket.send("999".encode(settings.CODING))
                    print("下载完成")
                    del self.shelve_obj[long]
                else:
                    self.socket.send("000".encode(settings.CODING))
                    print("文件下载出错")
        elif header_dic["status"] == "210":

            self.socket.send(header_dic["status"].encode(settings.CODING))
            print(header_dic["status_msg"])

    def resume(self):
        """
        断点续传
        :return:
        """
        if len(self.shelve_obj.keys()) == 0:
            return
        print("未传送完成文件".center(50, "-"))
        for k in self.shelve_obj.keys():
            relative_path = self.shelve_obj[k]["s_file_path"].replace(self.home_path, "")
            print("序号:%s,文件名:%s,文件大小:%s,文件地址:%s" %
                  (k, self.shelve_obj[k]["filename"], self.shelve_obj[k]["file_size"], relative_path))
        while True:
            print("请输入继续传送文件的序号,退出请输“q”")
            choice = input(">>")
            if not choice:
                continue
            elif choice == "q":
                return
            elif choice.isdigit():
                file_path = os.path.join(os.path.join(self.home_path, self.username),
                                         self.shelve_obj[choice]["s_file_path"]).rstrip(".download")
                filename = self.shelve_obj[choice]["filename"].rstrip(".download")
                complete_size = self.shelve_obj[choice]["file_size"]
                incomplete_size = os.path.getsize(
                    os.path.join(os.path.join(settings.DOWN_PATH, self.username), self.shelve_obj[choice]["filename"]))
                header_dic = {"filename": filename, "s_file_path": file_path, "incomplete_size": incomplete_size}
                client_path = os.path.join(os.path.join(settings.DOWN_PATH, self.username), filename)
                header_dic["client_path"] = client_path
                msg = {"action_type": "resume", "filename": filename, "username": self.username}

                self.socket.send(json.dumps(msg).encode(settings.CODING))
                if int(choice) > 0 and int(choice) <= len(self.shelve_obj.keys()):
                    if self.socket.recv(3).decode(settings.CODING) == "999":
                        status = "500"
                        self.header(status, **header_dic)
                        header_dic = self.recv_header()

                        with open("%s.download" % header_dic["client_path"], "ab")as f:  # 接受真实的数据
                            while incomplete_size < complete_size:
                                line = self.socket.recv(settings.MAX_PACKET_SIZE)
                                f.write(line)
                                incomplete_size += len(line)

                                self.progress_bar(incomplete_size, complete_size)
                            f.close()
                            os.rename("%s.download" % header_dic["client_path"], header_dic["client_path"])
                            num = self.hash_md5(self.read_file(header_dic["client_path"]))
                            if num == header_dic["md5"]:
                                self.socket.send("999".encode(settings.CODING))
                                print("下载完成")
                                del self.shelve_obj[choice]
                            else:
                                self.socket.send("000".encode(settings.CODING))
                                print("文件下载出错")
            else:
                print("输入错误,请重新输入!")

    def put(self, data):
        """
        上传
        :param data:
        :return:
        """
        if len(data) == 2:
            username = data[1]
            filename = input("请输入上传文件名:")
        else:
            username = data[2]
            filename = data[1]
        c_file_path = os.path.join(os.path.join(settings.UP_PATH, username), filename)
        if os.path.isfile(c_file_path):
            msg = {"action_type": "put", "filename": filename, "username": username}
            self.socket.send(json.dumps(msg).encode(settings.CODING))

            res = self.socket.recv(3).decode(settings.CODING)
            if res == "999":
                status = "200"
                file_size = os.path.getsize(c_file_path)
                header_dic = {
                    "filename": data[1],
                    "md5": self.hash_md5(self.read_file(c_file_path)),
                    "file_size": file_size,
                    "s_file_path": self.server_file_path
                }
                self.header(status, **header_dic)
                if self.socket.recv(3).decode(settings.CODING) == "000":
                    ask = input("%s文件已存在,是否覆盖?" % filename)
                    if ask == "n":
                        self.socket.send("000".encode(settings.CODING))
                        return
                    elif ask == "y":
                        self.socket.send("999".encode(settings.CODING))
                    else:
                        print("输入错误")
                        self.socket.send("000".encode(settings.CODING))
                        return
                else:
                    self.socket.send("999".encode(settings.CODING))
                header_dic = self.recv_header()
                if header_dic["status"] == "300":
                    send_size = 0
                    with open(c_file_path, "rb")as f:
                        for line in f:
                            self.socket.send(line)
                            send_size += len(line)

                            self.progress_bar(send_size, file_size)

                        f.close()
                        res = self.socket.recv(3).decode(settings.CODING)
                        if res == "999":
                            print("上传成功!")
                        else:
                            print("上传失败!")
                else:
                    print(header_dic["status_msg"])
                    return
            else:
                return
        else:
            print("文件不存在")
            return

    def progress_bar(self, recv_size, file_size):
        """
        进度条
        :param recv_size: 已接收大小
        :param file_size: 总共大小
        :return:
        """
        rate = recv_size / file_size
        rate_num = int(rate * 100)
        number = int(50 * rate)
        r = ‘\r[%s%s]%d%%‘ % ("#" * number, " " * (50 - number), rate_num,)
        print("\r {}".format(r), end=" ")

    def login(self):
        """
        用户验证
        :return:
        """
        count = 0
        while count < 3:
            username = input("请输入用户名:").strip()
            if not username:
                continue
            password = input("请输入密码:").strip()
            msg = {"action_type": "login", "username": username, "password": password}
            self.socket.send(json.dumps(msg).encode(settings.CODING))

            header_dic = self.recv_header()
            if header_dic["status"] == "100":
                self.home_path = header_dic["home_path"]
                self.username = username
                print("登陆成功,欢迎%s" % username)
                self.terimal = "%s" % username
                return True
            elif header_dic["status"] == "110":
                print("用户名或密码错误")
                count += 1
                # return False

    def run(self):
        """
        与服务器的所有交互
        :return:
        """
        if not self.username:
            self.client_status = self.login()
        if self.client_status:
            self.resume()
            while True:
                print("输入help可看帮助")
                user_input = input("%s,请输入命令:" % self.terimal).strip()
                if not user_input:
                    continue
                data = user_input.split()
                cmd = data[0]
                data.append(self.username)      # [get,1.mp3,username]
                # print(data)
                if hasattr(self, cmd):
                    func = getattr(self, cmd)
                    func(data)
                else:
                    print("输入有误,请重新输入")

    def help(self, data):
        """
        帮助
        :param data:
        :return:
        """
        msg = {"get 文件名": "下载文件",
               "put 文件名": "上传文件",
               "dir": "查看当前路径",
               "cd 目标路径": "切换目录"
               }
        for k in msg:
            print("指令:“%s”,功能:%s" % (k, msg[k]))

    def dir(self, data):
        """
        查看当前目录
        :param data:
        :return:
        """
        msg = {"action_type": "dir",  "username": data[1]}
        self.socket.send(json.dumps(msg).encode(settings.CODING))

        msg_dic = self.recv_header()
        if msg_dic["status"] == "200":
            print(msg_dic["msg"])
        else:
            print(msg_dic["status_msg"])

    def cd(self, data):
        """
        切换目录
        :param data:
        :return:
        """
        if len(data) == 2:
            target = input("请输入切换到的目录:")
        else:
            target = data[1]
        msg = {"action_type": "cd", "target": target}
        self.socket.send(json.dumps(msg).encode(settings.CODING))

        msg_dic = self.recv_header()
        if msg_dic["status"] == "400":
            print("目录切换成功")
            self.server_file_path = msg_dic["path"]
            # print(msg_dic["path"])
            self.terimal = msg_dic["current_path"]
        else:
            print(msg_dic["status_msg"])

client = MYClient((‘127.0.0.1‘, 8080))
client.run()

  



server

bin\server

import os
import sys

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

if __name__ == "__main__":
    from core import main
    from conf import settings
    ftp_server = main.MYServer(settings.server_address)
    ftp_server.run()

conf\settings

import os

BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CONF_PATH = os.path.join(BASE_PATH, "conf")
SERVER_PATH = os.path.join(BASE_PATH, "core")
HOME_PATH = os.path.join(BASE_PATH, "home")

SERVER_ADDRESS = ("127.0.0.1", 8080)

REQUEST_QUEUEST_SIZE = 5
MAX_PACKET_SIZE = 8192
CODING = "utf-8"
ALLOW_REUSE_ADDRESS = False

用户初始化信息

import configparser
import hashlib

config = configparser.ConfigParser()
config["alex"] = {}
password = "abc123"
n = hashlib.md5()
n.update(password.encode("utf-8"))
config["alex"]["name"] = "alex"
config["alex"]["password"] = n.hexdigest()
config["alex"]["quato"] = "5"

config["egon"] = {}
password = "efg456"
m = hashlib.md5()
m.update(password.encode("utf-8"))
config["egon"]["name"] = "egon"
config["egon"]["password"] = m.hexdigest()
config["alex"]["quato"] = "3"

config["jack"] = {}
password = "hij789"
l = hashlib.md5()
l.update(password.encode("utf-8"))
config["jack"]["name"] = "jack"
config["jack"]["password"] = l.hexdigest()
config["alex"]["quato"] = "2.5"

with open("config.ini", "w")as f:
    config.write(f)

core\main

import socket
import os
import json
import hashlib
import configparser
import struct
import subprocess
from conf import settings

class MYServer(object):
    """
    ftp服务端
    """
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    STATUS = {
        "100": "用户验证成功!",
        "110": "用户名或密码错误!",
        "200": "文件存在",
        "210": "文件不存在",
        "300": "存储空间足够",
        "310": "存储空间不足",
        "400": "路径存在",
        "410": "路径不存在",
        "500": "文件续传",
        "999": "文件传输成功",
        "000": "文件传输失败"
    }

    def __init__(self, server_address):
        self.server_address = server_address
        self.socket = socket.socket(self.address_family, self.socket_type)
        self.server_bind()
        self.server_listen()
        self.user_current_dir = ""
        self.file_size = 0

    def server_bind(self):
        """
        绑定
        :return:
        """
        if settings.ALLOW_REUSE_ADDRESS:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)

    def server_listen(self):
        """
        监听
        :return:
        """
        self.socket.listen(settings.REQUEST_QUEUEST_SIZE)

    def run(self):
        """
        建立连接,启动socket server
        :return:
        """
        while True:
            self.conn, self.client_addr = self.socket.accept()
            try:
                self.manage()
            except ConnectionRefusedError:
                print("客户端发生错误,断开连接")
                self.socket.close()

    def manage(self):
        """
        处理与用户的所有指令交互
        :return:
        """
        while True:
            data = self.conn.recv(settings.MAX_PACKET_SIZE)    # 接收客户端指令
            if not data:
                print("连接断开... ")
                del self.conn, self.client_addr
                break

            cmd_data = json.loads(data.decode(settings.CODING))
            action_type = cmd_data["action_type"]
            if action_type:
                if hasattr(self, action_type):
                    func = getattr(self, action_type)
                    func(cmd_data)
            else:
                print("未接收到有效指令")

    def header(self, status, **kwargs):
        """
        制作、发送报头
        :param status: 状态码
        :param kwargs:
        :return:
        """
        header_dic = kwargs
        header_dic["status"] = status
        header_dic["status_msg"] = self.STATUS[status]
        header_dic["home_path"] = settings.HOME_PATH
        # print(header_dic)
        header_json = json.dumps(header_dic)
        header_bytes = header_json.encode(settings.CODING)
        self.conn.send(struct.pack("i", len(header_bytes)))    # header_dic的大小传送给客户端
        self.conn.send(header_bytes)                      # header_dic数据传送给客户端

    def recv_header(self):
        """
        接收报头
        :return:
        """
        header = self.conn.recv(4)      # 接收报头
        header_size = struct.unpack("i", header)[0]
        header_bytes = self.conn.recv(header_size)     # 接收报头信息
        header_json = header_bytes.decode(settings.CODING)
        header_dic = json.loads(header_json)
        return header_dic

    def read_info(self):
        """
        加载所有账户信息
        :return:
        """
        conf = configparser.ConfigParser()
        conf.read(r"%s/%s" % (settings.CONF_PATH, "config.ini"))
        return conf

    def login(self, data):
        """
        用户登陆验证
        :param data: 指令、用户名、密码
        :return:
        """
        username = data["username"]
        password = data["password"]
        conf = self.read_info()
        psd = self.hash_md5(password.encode(settings.CODING))
        if username in conf:
            if psd == conf[username]["password"]:
                print("认证成功")
                self.header("100")
                self.user_current_dir = os.path.join(settings.HOME_PATH, username)
                return True
            else:
                self.header("110")
                print("认证失败")
                return False
        else:
            self.header("110")
            print("认证失败")
            return False

    def read_file(self, path):
        """
        打开文件
        :param path: 文件路径
        :return:
        """
        with open(path, "rb") as f:
            return f.read()

    def hash_md5(self, msg):
        """
        md5加密
        :param msg: 加密信息
        :return:
        """
        m = hashlib.md5()
        m.update(msg)
        # print(m.hexdigest())
        return m.hexdigest()

    def get(self, data):
        """
        下载
        :param data:  指令、文件名,用户名、服务器路径
        :return:
        """
        if data["s_file_path"] is None:
            file_path = os.path.join(os.path.join(settings.HOME_PATH, data["username"]), data["filename"])
        else:
            file_path = os.path.join(data["s_file_path"], data["filename"])
        if os.path.isfile(file_path):
            status = "200"
            self.file_size = os.path.getsize(file_path)
            header_dic = {
                "filename": data["filename"],
                "md5": self.hash_md5(self.read_file(file_path)),
                "file_size":  self.file_size,
                "s_file_path": file_path
            }
            self.header(status, **header_dic)
        else:
            status = "210"
            self.header(status)

        if self.conn.recv(3).decode(settings.CODING) == "200":
            if self.conn.recv(4).decode(settings.CODING) == "999":
                send_size = 0
                with open(file_path, "rb")as f:
                    for line in f:
                        self.conn.send(line)
                        send_size += len(line)

                        self.progress_bar(send_size, self.file_size)

                    f.close()
                    res = self.conn.recv(4).decode(settings.CODING)
                    if res == "999":
                        print("下载成功!")
                    else:
                        print("下载失败!")
            else:
                return
        else:
            print(self.STATUS["210"])

    def progress_bar(self, recv_size, file_size):
        """进度条
        :param recv_size: 已接收大小
        :param file_size: 总共大小
        :return:
        """
        rate = recv_size / file_size
        rate_num = int(rate * 100)
        number = int(50 * rate)
        r = ‘\r[%s%s]%d%%‘ % ("#" * number, " " * (50 - number), rate_num,)
        print("\r {}".format(r), end=" ")

    def put(self, data):
        """
        上传
        :param data: 指令、文件名,用户名
        :return:
        """
        self.conn.send("999".encode(settings.CODING))
        header_dic = self.recv_header()
        if header_dic["s_file_path"] is None:
            file_path = os.path.join(os.path.join(settings.HOME_PATH, data["username"]), data["filename"])
        else:
            file_path = os.path.join(header_dic["s_file_path"], data["filename"])
        quato = float(self.read_info()[data["username"]]["quato"]) * 1024 * 1024 * 1024
        full_size = 0
        for parent, dirs, files in os.walk(file_path):
            for file in files:
                fullname = os.path.join(parent, file)
                filesize = os.path.getsize(fullname)
                full_size += filesize
        header_dic.pop("status")
        header_dic["file_path"] = file_path
        if full_size + header_dic["file_size"] <= quato:
            status = "300"
        else:
            status = "310"
        if os.path.isfile(file_path):
            print("%s文件已存在" % data["filename"])
            self.conn.send("000".encode(settings.CODING))
        else:
            self.conn.send("999".encode(settings.CODING))
        if self.conn.recv(3).decode(settings.CODING) == "999":
            self.header(status, **header_dic)
            if status == "300":
                recv_size = 0
                with open(file_path, "wb")as f:  # 接受真实的数据
                    while recv_size < header_dic["file_size"]:
                        line = self.conn.recv(settings.MAX_PACKET_SIZE)
                        f.write(line)
                        recv_size += len(line)

                        self.progress_bar(recv_size, header_dic["file_size"])

                    f.close()
                    num = self.hash_md5(self.read_file(file_path))
                    # print(num)
                    if num == header_dic["md5"]:
                        self.conn.send("999".encode(settings.CODING))
                        print("上传成功")
                    else:
                        self.conn.send("000".encode(settings.CODING))
                        print("文件上传失败")
            else:
                print(self.STATUS[status])
        else:
            return

    def dir(self, data):
        """
        查看当前目录
        :param data: 指令、用户名
        :return:
        """
        cmd_obj = subprocess.Popen("dir %s" % self.user_current_dir, shell=True, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        stdout = cmd_obj.stdout.read()
        stderr = cmd_obj.stderr.read()
        result = stdout + stderr

        if not result:
            result = "当前目录下没有任何文件".encode("gbk")

        status = "200"
        msg = {"msg": result.decode("gbk")}
        self.header(status, **msg)

    def cd(self, data):
        """
        改变目录
        :param data: 指令,目标路径
        :return:
        """
        current_dir = os.path.abspath(os.path.join(self.user_current_dir, data["target"]))
        print(current_dir)
        if os.path.isdir(current_dir):
            if current_dir.startswith(settings.HOME_PATH):
                status = "400"
                current_path = current_dir.replace(settings.HOME_PATH, "")
                self.user_current_dir = current_dir
                msg = {"path": current_dir, "current_path": current_path}
                self.header(status, **msg)
            else:
                status = "410"
                self.header(status)
        else:
            status = "410"
            self.header(status)

    def resume(self, data):
        """
        断点续传
        :param data: 指令、文件名,用户名
        :return:
        """
        self.conn.send("999".encode(settings.CODING))
        header_dict = self.recv_header()
        incomplete_size = header_dict["incomplete_size"]
        complete_size = os.path.getsize(header_dict["s_file_path"])
        balance = complete_size - incomplete_size
        header_dict["balance"] = balance
        header_dict["md5"] = self.hash_md5(self.read_file(header_dict["s_file_path"]))
        status = "500"
        header_dict.pop("status")
        self.header(status, **header_dict)
        with open(header_dict["s_file_path"], "rb")as f:
            f.seek(incomplete_size)
            for line in f:
                self.conn.send(line)
                incomplete_size += len(line)

                self.progress_bar(incomplete_size, complete_size)

            f.close()
            res = self.conn.recv(4).decode(settings.CODING)
            if res == "999":
                print("下载成功!")
            else:
                print("下载失败!")

# server = MYServer((‘127.0.0.1‘, 8080))
# server.run()

README

服务端入口:bin-->server.py
客户端入口:client.py
客户端默认下载到download中
客户端从upload文件夹中上传文件
用户信息存在conf-->config.ini中

  

原文地址:https://www.cnblogs.com/fantsaymwq/p/10105268.html

时间: 2024-10-11 02:05:42

FTP程序的相关文章

Python开发程序:支持多用户在线的FTP程序

作业:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当前目录下文件 允许上传和下载文件,保证文件一致性 文件传输过程中显示进度条 附加功能:支持文件的断点续传(仅下载) 程序 1.最最重要的readme: ### 作者介绍: * author:lzl ### 博客地址: * http://www.cnblogs.c

开发一个支持多用户在线的FTP程序

一,项目题目:开发一个支持多用户在线的FTP程序 二,项目要求: 1.用户加密认证 2.允许同时多用户登录 3.每个用户有自己的家目录 ,且只能访问自己的家目录 4.对用户进行磁盘配额,每个用户的可用空间不同 5.允许用户在ftp server上随意切换目录 6.允许用户查看当前目录下文件 7.允许上传和下载文件,保证文件一致性(md5) 8.文件传输过程中显示进度条 9.附加功能:支持文件的断点续传 三,注意事项: 基本要求. 完成1,2,3,5,6,7,8 实力选手. 完成 上条 及需求4

【python练习】基于socket的FTP程序 v1.1.0(支持并发)

增加功能 1.在FTP(1.0.0)的基础上,支持了多并发的功能 2.允许配置最大并发数,比如允许只有10个并发用户 程序功能: 本程序模拟实现了一个FTP程序: 1.程序分为客户端和服务端 2.用户可以登录和注册账号,登录密码有MD5加密 3.每个用户有自己的家目录 ,且只能访问自己的家目录 4.用户可以随意切换目录(仅限自己的家目录) 5.允许用户查看当前目录下文件 6.允许上传和下载文件,保证文件一致性(md5),(不允许下载/上传文件夹,会出现不可恢复bug,用户配置文件需要重置.时间原

python之FTP程序(支持多用户在线)

转发注明出处:http://www.cnblogs.com/0zcl/p/6259128.html,这次博客写了很久~~ 一.需求 1. 用户加密认证 (完成)2. 允许同时多用户登录 (完成)3. 每个用户有自己的家目录 ,且只能访问自己的家目录(完成)4. 对用户进行磁盘配额,每个用户的可用空间不同(完成)5. 允许用户在ftp server上随意切换目录cd(完成)6. 允许用户查看当前目录下文件ls(完成)7. 允许上传put和下载get文件(完成),保证文件一致性(此需求不做)8. 文

用win8电脑写java的ftp程序遇到的一些问题

1.搭建ftp环境遇到的问题: 刚开始在网上搜到一些方法,但是由于是win8的电脑,并没有看到预想中的sII网络管理和用户分组管理,后来经过搜索,在 控制面板-所有控制面板项-程序和功能-启用或关闭功能 中找到.Net Framwork3.5和勾选上了以下选项,解决了IIS问题. 2.打开IIS管理器后,然后根据网上的方法建立站点,将自动启动站点,然后要添加FTP发布,ip地址选择下拉框中的ip,默认端口就行了,按照下面方式选择. 3.添加FTP授权规则,可以指定现有用户,也可以先去添加用户 4

python 多用户在线的FTP程序

要求: 1.用户加密认证 2.允许同时多用户登录 3.每个用户有自己的家目录 ,且只能访问自己的家目录 4.对用户进行磁盘配额,每个用户的可用空间不同 5.允许用户在ftp server上随意切换目录 6.允许用户查看当前目录下文件 7.允许上传和下载文件,保证文件一致性 8.文件传输过程中显示进度条 9.附加功能:支持文件的断点续传 README: 设计说明 1.client连接server端需要验证账号密码,密码使用MD5加密传输. 2.用户信息保存在本地文件中,密码MD5加密存储.磁盘配额

python作业:高级FTP程序

要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当前目录下文件 允许上传和下载文件,保证文件一致性 文件传输过程中显示进度条 附加功能:支持文件的断点续传 程序流程图: 程序Readme: MiniFTP主要是由三部分组成:服务器端.客户端.管理端.本文主要就是介绍以上三部分内容. 系统初始配置 管理员账号 用户名:admin 密码:password

Python:socket实现ftp程序

刚开始学习socket编程,还不是特熟练,码了好长时间,中间遇到许多问题,记录一下用socketserver写ftp server端: 1 #!/usr/bin/env python 2 3 import socketserver,os 4 5 class FTP(socketserver.BaseRequestHandler): 6 def handle(self): 7 def clientsend(filename): 8 f = open('/ftp/%s' %filename,'w')

第五十六节,python实现支持并发、断点续传的Ftp程序

一.要求 1.用户md5认证 2.支持多用户同时登陆(并发) 3.进入用户的命令行模式,支持cd切换目录,ls查看目录子文件 4.执行命令(ipconfig) 5.传输文件: a.支持断点续传 b.传输中显示进度条 二.思路 1.客户端用户登录和注册: a.客户端仅提供用户名和密码,选择登录或注册,b.服务器端进行注册并将加密后的密码写入文件,最后返回给客户端是否登录或注册成功 2.ls和cd命令 a.客户端输入命令,服务器端处理并返回给客户端 3.执行命令: a.客户端发送需要执行的命令b.服