文件的上传和下载

ftp 文件服务器

【1】 分为服务端和客户端,要求可以有多个客户端同时操作。

【2】 客户端可以查看服务器文件库中有什么文件。

【3】 客户端可以从文件库中下载文件到本地。

【4】 客户端可以上传一个本地文件到文件库。

【5】 使用print在客户端打印命令输入提示,引导操作

FTP --> 服务端

在这里插入图片描述

"""
文件服务器 服务端程序
"""

from socket import *
from threading import Thread
import os, time

# 全局变量定义地址
HOST = "0.0.0.0"
PORT = 8888
ADDR = (HOST, PORT)

# 文件库位置
FTP = "/home/tarena/FTP/"


# 具体处理客户端请求
class FTPServer(Thread):
    def __init__(self, connfd):
        self.connfd = connfd
        super().__init__()

    def do_list(self):
        # 获取文件列表
        file_list = os.listdir(FTP)
        if not file_list:
            # 文件列表为空
            self.connfd.send(b"FAIL")
            return
        else:
            self.connfd.send(b"OK")
            time.sleep(0.1)
            # 发送文件列表
            files = "\n".join(file_list)
            self.connfd.send(files.encode())

    # 处理上传
    def do_put(self, filename):
        # 判断文件是否存在
        if os.path.exists(FTP + filename):
            self.connfd.send(b"FAIL")
            return
        self.connfd.send(b"OK")
        # 接收文件
        f = open(FTP + filename, 'wb')
        while True:
            data = self.connfd.recv(1024)
            if data == b'##':
                break
            f.write(data)
        f.close()

    # 处理下载
    def do_get(self, filename):
        try:
            f = open(FTP + filename, 'rb')
        except:
            self.connfd.send(b'FAIL')
            return
        self.connfd.send(b'OK')
        # 发送文件
        while True:
            data = f.read(1024)
            if not data:
                break
            self.connfd.send(data)
        f.close()
        time.sleep(0.1)
        self.connfd.send(b"##")

    # 处理客户端   总分模型部分
    def run(self):
        while True:
            # 接收某个客户端的所有请求
            data = self.connfd.recv(1024).decode()
            # print(data)
            if not data or data == 'EXIT':
                break
            elif data == "LIST":
                self.do_list()
            elif data[:3] == "PUT":
                filename = data.split(' ')[-1]
                self.do_put(filename)
            elif data[:3] == "GET":
                filename = data.split(' ')[-1]
                self.do_get(filename)

        self.connfd.close()


# 创建多线程并发模型
def main():
    # 创建tcp套接字
    sock = socket()
    sock.bind(ADDR)
    sock.listen(5)

    print("Listen the port %d..." % PORT)
    while True:
        # 循环接收端连接
        try:
            connfd, addr = sock.accept()
            print("Connect from", addr)
        except KeyboardInterrupt:
            sock.close()
            return

        # 创建新的线程,处理客户端具体请求事务
        t = FTPServer(connfd)
        t.setDaemon(True)
        t.start()


if __name__ == '__main__':
    main()

尽量使用进程完成无阻塞的并发行为

  • 不使用c作为解释器 (Java C#)

Guido的声明:http://www.artima.com/forums/flat.jsp?forum=106&thread=214235

Guido的声明
在这里插入图片描述

FTP --> 客户端

"""
ftp 客户端
"""
from socket import *
import time
import sys

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


# 具体的请求方法
class FTPClient:
    def __init__(self, sock):
        self.sock = sock

    def do_list(self):
        # 发送请求
        self.sock.send(b'LIST')
        # 等待反馈
        result = self.sock.recv(128)
        # 根据反馈分情况讨论
        if result == b"OK":
            # 接受文件列表
            files = self.sock.recv(1024 * 1024)
            print(files.decode())
        else:
            print("文件库为空")

    def do_exit(self):
        self.sock.send(b"EXIT")
        self.sock.close()
        sys.exit("谢谢使用")

    # 上传文件
    def do_put(self, filename):
        try:
            f = open(filename, "rb")
        except:
            print("要上传的文件不存在")
            return

        # 提取真正的文件名,去除路径
        filename = filename.split('/')[-1]

        # 发送请求
        data = "PUT " + filename
        self.sock.send(data.encode())
        # 等待反馈 是否允许上传
        result = self.sock.recv(128)
        if result == b'OK':
            # 上传文件
            while True:
                data = f.read(1024)
                if not data:
                    break
                self.sock.send(data)
            f.close()
            time.sleep(0.1)
            self.sock.send(b"##")
        else:
            print("该文件存在")

    # 下载文件
    def do_get(self, filename):
        # 发送请求
        data = "GET " + filename
        self.sock.send(data.encode())
        # 等待反馈 是否允许下载
        result = self.sock.recv(128)
        if result == b'OK':
            # 下载文件
            f = open(filename, 'wb')
            while True:
                data = self.sock.recv(1024)
                if data == b'##':
                    break
                f.write(data)
            f.close()
        else:
            print("该文件不存在")


# 网络连接启动程序
def main():
    sock = socket()
    sock.connect(ADDR)  # 建立网络连接

    # 通过对象调用类中具体方法完成请求
    ftp = FTPClient(sock)

    # 循环输入命令
    while True:
        print("""
        ========== 命令选项 ===========
                    list
                  get file
                  put file
                    exit
        ==============================
        """)
        cmd = input("命令:")
        if cmd == 'list':
            ftp.do_list()
        elif cmd[:3] == 'put':
            filename = cmd.split(' ')[-1]
            ftp.do_put(filename)
        elif cmd[:3] == 'get':
            filename = cmd.split(' ')[-1]
            ftp.do_get(filename)
        elif cmd == "exit":
            ftp.do_exit()
        else:
            print("请输入正确指令")


if __name__ == '__main__':
    main()

执行需先执行服务端后再执行客户端

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值