Python3文件传输

文档分析

需求 :
* 分为服务端和客户端,要求可以有多个客户端同时操作。
* 客户端可以查看服务器文件库中有什么文件。
* 客户端可以从文件库中下载文件到本地。
* 客户端可以上传一个本地文件到文件库。
* 使用print在客户端打印命令输入提示,引导操作

1. 文件库可能为空,此时看不了文件库
2. 要下载的文件不存在
3. 上传时文件库有同名的文件

技术点 :

网络: tcp
并发模型 :  多进程  多线程 并发

功能划分和封装: 封装

框架搭建 : 函数
 查看文件库内容
 下载文件
 上传文件
 退出

协议设计 :

         请求类型   数据参量
  查看   LOOK

  上传     UP            文件名/带路径的文件

  下载     DOWN         文件名

  退出     EXIT

  服务端反馈约定 :   OK
                        NO

具体功能模块设计:

        框架搭建   服务端 :
        客户端 :
        
查看文件库内容
      客户端 : 1. 发起请求
                 2. 等待服务端反馈结果
                 3. Yes -> 接收文件列表
                    No -> 结束

      服务端 : 1. 接收请求
                 2. 判断请求是否可以完成
                    将反馈结果发送给客户端
                 3. Yes 发送文件列表
                     No  结束

上传文件

     客户端 : 发送请求
              等待反馈
              Yes  上传文件
              No   结束

     服务端 : 接收请求
              判断文件是否已存在
              发送反馈
              Yes 接收文件
              No  结束

下载文件

   客户端 : 发送请求
             发送数据参量  文件名
                  等待反馈结果

    服务端 : 接收请求
                  判断文件是否存在  存在/不存在(文件名有误)
     发送反馈结果

退出

客户端:
        	考虑异常退出的情况
服务端:
        考虑客户端异常退出的情况

注:后续还需优化处理,写的不是很好,只供参考

服务端代码

# -*- coding: UTF-8 -*-
'''
PyCharm
@Project :文件传输
@File    :ftp_server.py
@Author  :
@Date    :2020/10/24
'''
"""
    服务端
"""
from socket import *
from multiprocessing import Process
from signal import *
import os, time

# 文件库位置
ilbrary = '/home/桌面/学习/'

# 下载位置
local_ilbrary = '/home/桌面/下载1/'

file = os.listdir(ilbrary)
# print(files)

POST = '0.0.0.0'
PORT = 8888
ADDR = (POST, PORT)


# 处理查看文件列表
def files(connfd):
    str_file = ''
    if file == []:
        connfd.send('无文件'.encode())
    for filename in file:

        str_file += filename + '\n'
    connfd.send(str_file.encode())
    time.sleep(0.1)
    connfd.send(b'##')


# 处理上传
def upload_file(connfd, fileaddr):
    filename = fileaddr.split('/')[-1]
    if os.path.exists(ilbrary + filename):
        connfd.send('上传文件已存在'.encode())
        return
    connfd.send('OK'.encode())
    up_file = open(ilbrary + filename, 'wb')
    while True:
        data = connfd.recv(1024)
        if data == b'##':
            break
        up_file.write(data)
    up_file.close()


# 处理下载
def download_file(connfd, filename):
    if os.path.exists(ilbrary + filename):
        file = open(ilbrary + filename, 'rb')
        if os.path.exists(local_ilbrary + filename):
            connfd.send('下载的文件重复'.encode())
            return
        else:
            down_file = open(local_ilbrary + filename, 'wb')
            while True:
                data = file.read(1024)
                down_file.write(data)
                if not data:
                    break
        connfd.send('下载成功'.encode())

        file.close()
        down_file.close()

    else:
        connfd.send('文件不存在'.encode())
        return


# 处理退出
def exits(connfd):
    connfd.send('拜拜'.encode())


# 处理请求
def request(connfd):
    while True:
        try:
            data = connfd.recv(1024)
            tmp = data.decode().split(' ', 1)
            print(tmp)
        except KeyboardInterrupt:
            return

        if not data:
            break
        if tmp[0] == 'LOOK':
            files(connfd)
        elif tmp[0] == 'UP':
            upload_file(connfd, tmp[1])
        elif tmp[0] == 'DOWN':

            download_file(connfd, tmp[1])

        elif tmp[0] == 'EXIT':
            exits(connfd)
    connfd.close()


# 启动函数
def main():
    socketed = socket()
    socketed.bind(ADDR)
    socketed.listen(5)
    signal(SIGCHLD,SIG_IGN)
    while True:
        try:
            connfd, addr = socketed.accept()
        except KeyboardInterrupt:
            socketed.close()
            return

        process = Process(target=request, args=(connfd,))
        Process.daemon=True
        process.start()


if __name__ == '__main__':
    main()

客户端代码

# -*- coding: UTF-8 -*-
'''
PyCharm
@Project :文件传输
@File    :ftp_client.py
@Author  :
@Date    :2020/10/24
'''
"""
    客户端
"""

from socket import *
import sys, time

#服务器地址
ADDR = ('127.0.0.1', 8888)


# 文件列表
def file_list(socketed, msg):
    socketed.send(msg.encode())
    while True:
        data = socketed.recv(1024)
        print('文件列表:')
        if  data == b'##':
            return
        print(data.decode())


# 下载文件
def down_file(socketed):
    filename = input('要下载的文件名:')
    afreement = 'DOWN %s' % filename

    socketed.send(afreement.encode())
    data = socketed.recv(1024)
    if not data:
        return
    print(data.decode())




# 上传文件
def up_file(socketed):
    fileaddr = input('要上传的文件地址:')
    try:
        file = open(fileaddr, 'rb')

    except FileNotFoundError:
        print('文件不存在')
        return
    afreement = f'UP {fileaddr}'
    socketed.send(afreement.encode())
    data = socketed.recv(1024)

    if data == b"OK":
        while True:
            message = file.read(1024)
            if not message:
                break
            socketed.send(message)
        print('文件上传成功')
        file.close()
        time.sleep(0.1)
        socketed.send(b'##')
    else:
        print(data.decode())


# 退出
def sign_out(socketed, msg):
    socketed.send(msg.encode())
    data = socketed.recv(1024)
    if data.decode() == '拜拜':
        sys.exit('谢谢使用')




def main():
    socketed = socket()
    socketed.connect(ADDR)
    while True:
        print('--------功能选项--------')
        print('LOOK---UP---DOWN---EXIT')

        try:
            msg = input('请输入:')
            if not msg:
                break
        except KeyboardInterrupt:
            socketed.close()
            break

        if msg == 'LOOK':
            file_list(socketed, msg)
        elif msg == 'UP':
            up_file(socketed)
        elif msg == 'DOWN':
            down_file(socketed)
        elif msg == 'EXIT':
            sign_out(socketed, msg)
        else:
            print('请输入有效指令!')

if __name__ == '__main__':
    main()

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值