Python笔记day34(网络)|实现ftp部分功能

版权声明:转载请注明来源 https://blog.csdn.net/qq_34755081/article/details/82051759

1,内容回顾

# 网络编程
# 互联网协议 —— 七层 :osi协议
# 五层
# 应用层     python
# 传输层     tcp/udp
# 网络层     ip   路由器
# 数据链路层 arp  交换机
# 物理层     网卡 双绞线
# arp 通过ip找mac地址
# 交换机 :广播 单播 组播
# ip协议 :ip地址的格式
    # ip地址 一台机器在一个网络内唯一的标识
    # 子网掩码  ip地址与子网掩码做按位与运算,得到的结果是网段
    # 网关ip 局域网内的机器访问公网ip,就通过网关访问
# tcp 面向流的 可靠 全双工 三次握手 四次挥手 —— 黏包
# udp 面向数据包 不可靠

# 黏包
# 什么是黏包
# 怎么解决
    # 在发送信息信息之前 先告诉对方要发的数据有多大
    # struct模块将要发送数据的大小固定化,无论如何就发4个字节
    # 自定义协议的概念

# 验证客户端合法性 hmac

# 处理并发问题
# socketserver

2,实现ftp部分功能

  1. 多用户同时登陆
  2. 用户登陆,加密认证
  3. 上传/下载文件 ,保证文件一致性
  4. 不同用户家目录不同,且只能访问自己的家目录
  5. 对用户进行磁盘配额、不同用户配额可不同
  6. 用户登陆server后,可在家目录权限下切换子目录
  7. 查看当前目录下文件,新建文件夹 有
  8. 删除文件和空文件夹
  9. 充分使用面向对象知识
  10. 传输过程中现实进度条
  11. 支持断点续传
    (以下代码只实现了以上部分功能)

server端

1)server端文件结构
这里写图片描述
2)server端代码
bin\start.py

import os
import sys
from conf import settings
sys.path.append(os.path.dirname(os.getcwd()))
import socketserver
from core.server import MyFtpServer
if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(settings.addr, MyFtpServer)
    server.serve_forever()

conf\settings.py

addr = ('127.0.0.1',8080)
code = 'utf-8'
home_path = r'C:\Users\Administrator\PycharmProjects\ftp\home'
space = 1024*1024*2
user_info = r'C:\Users\Administrator\PycharmProjects\ftp\db\userinfo'
pickle_path = r'C:\Users\Administrator\PycharmProjects\ftp\db\user_pickle'

core\server.py

import socketserver
import json
from core import views
from conf import settings
class MyFtpServer(socketserver.BaseRequestHandler):
    def handle(self):
        msg = self.my_recv()
        #消息转发 把任务转给views中 对应的方法
        op_str = msg['operation']
        if hasattr(views,op_str):
            func = getattr(views,op_str)
            ret = func(msg)
            self.my_send(ret)
        #{'username':'','password':'',"operation":''}
        #判断登录 注册 查看目录 上传文件
        #反射

    def my_recv(self):#派生方法
        msg = self.request.recv(1024)
        msg.decode(settings.code)
        msg = json.loads(msg)
        return msg
    def my_send(self,msg):
        msg = json.dumps(msg).encode(settings.code)
        self.request.send(msg)

core\user.py

import os
from conf import settings
class User:
    def __init__(self,name):
        self.name = name
        self.home = os.path.join(settings.home_path,name)
        self.cur_path = self.home
        self.disk_space = settings.space
        self.file_size = 0

core\views.py

import os,pickle
from core.user import User
from conf import settings
def login(msg):
    print(msg)
def register(msg):
    # username,password
    # 创建一个属于这个用户的家目录并记录下来
    # 把用户名密码 写进userinfo文件里,记录用户名
    # 记录用户的初始磁盘配额
    # 记录文件大小
    # 记录用户当前所在的目录
    user_obj = User(msg['username'])#记录用户信息到内存
    pickle_path = os.path.join(settings.pickle_path,msg['username'])
    with open(pickle_path,'wb')as f:
        pickle.dump(user_obj,f)
    os.mkdir(user_obj.home)#创建一个属于用户的家目录
    with open(settings.user_info,'a')as f:
        f.write('%s|%s|%s\n'%(msg['username'],msg['password'],pickle_path))
    return True
def upload():
    pass
def download():
    pass

db\userinfo 内容为注册时自动填入
db\user_pickle\名字 内容为注册时自动填入
home\名字 为注册时自动生成

client端

1)client文件结构
这里写图片描述
2)client端代码
bin\start.py

import  os
import sys
sys.path.append(os.path.dirname(os.getcwd()))
from core import client
if __name__ == '__main__':
    client.main()

core\auth_client.py

import json
from  core.socket_client import MysocketClient
class Auth:
    __instance = None
    def __new__(cls,*args,**kwargs):
        '''单例模式 ------  防止重复登录时重复建立连接'''
        if not cls.__instance:
            obj = object.__new__(cls)
            cls.__instance = obj

        return cls.__instance


    def __init__(self):
        self.socket = MysocketClient()
        self.username = None

    def login(self):
        username = input('username: ')
        password = input('password: ')
        if username.strip() and password.strip():
            #send{'username':'alex','password':'123456'}

            self.socket.mysend({'username':username,'password':password,'operation':'login'})
            ret = self.socket.sk.recv(1024)
    def register(self):
        username = input('username: ')
        password1 = input('password: ')
        password2 = input('password: ')
        if username.strip() and password1.strip() and password1 ==password2:
            self.socket.mysend({'username':username,'password':password1,'operation':'register'})
            ret = self.socket.sk.recv(1024)

core\client.py

from core.auth_client import Auth
def main():
    auth_obj =None
    start_l = [('登录','login'),('注册','register'),('退出','exit')]
    for index,item in enumerate(start_l,1):
        print(index,item[0])
    while True:
        try:
            num = int(input('>>>'))
            func_str = start_l[num-1][1]
        except:
            print('您输入的信息犹有误')
            #字符串数据类型方法
        if hasattr(Auth,func_str):
            auth_obj = Auth()
            func = getattr(auth_obj,func_str)
            ret = func()
            if ret :break
        elif auth_obj:
            auth_obj.socket.sk.close()
            exit()
        else:
            exit()

core\socket_client.py

import json
import socket
class MysocketClient:

    def __init__(self):
        self.sk = socket.socket()
        self.sk.connect(('127.0.0.1',8080))
    def mysend(self,msg):
        ret_json = json.dumps(msg)
        self.sk.send(ret_json.encode('utf-8'))

猜你喜欢

转载自blog.csdn.net/qq_34755081/article/details/82051759