ftp文件服务器
  1. 技术点分析
    1. 并发模型:多线程
    2. 数据传输:tcp
  2. 结构设计
    1. 客户端发送请求,打印请求提示界面
    2. 文件传输功能封装为类
  3. 功能分析
    1. 网络搭建
    2. 查看文件库信息
    3. 下载文件
    4. 上传文件
    5. 客户端退出
  4. 协议
    1. L表示请求文件列表

server

"""
ftp 文件服务器
并发网络功能训练
"""

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

#  全局变量
HOST = '0.0.0.0'
PORT = 8080
ADDR = (HOST, PORT)
FTP = "/home/tarena/FTP/"  # 文件库路径


# 将客户端请求功能封装为类
class FtpServer:
    def __init__(self, connfd, FTP_PATH):
        self.connfd = connfd
        self.path = FTP_PATH

    def do_list(self):
        #  获取文件列表
        files = os.listdir(self.path)
        if not files:
            self.connfd.send("该文件类别为空".encode())
            return
        else:
            self.connfd.send(b'OK')
            sleep(0.1)
        fs = ''
        for file in files:
            if file[0] != '.' and \
                    os.path.isfile(self.path + file):
                fs += file + '\n'
        self.connfd.send(fs.encode())

    def do_get(self, filename):
        try:
            fd = open(self.path + filename, 'rb')
        except Exception:
            self.connfd.send('文件不存在'.encode())
            return
        else:
            self.connfd.send(b'OK')
            sleep(0.1)
        #  发送文件内容
        while True:
            data = fd.read(1024)
            if not data:  # 文件结束
                sleep(0.1)
                self.connfd.send(b'##')
                break
            self.connfd.send(data)

    def do_put(self, filename):
        if os.path.exists(self.path + filename):
            self.connfd.send("该文件已存在".encode())
            return
        self.connfd.send(b'OK')
        fd = open(self.path + filename, 'wb')
        # 接收文件
        while True:
            data = self.connfd.recv(1024)
            if data == b'##':
                break
            fd.write(data)
        fd.close()


# 客户端请求处理函数
def handle(connfd):
    #  选择文件夹
    cls = connfd.recv(1024).decode()
    FTP_PATH = FTP + cls + '/'
    ftp = FtpServer(connfd, FTP_PATH)
    while True:
        # 接受客户端请求
        data = connfd.recv(1024).decode()
        #  如果客户端断开返回data为空
        if not data or data[0] == 'Q':
            return
        elif data[0] == 'L':
            ftp.do_list()
        elif data[0] == 'G':
            filename = data.split(' ')[-1]
            ftp.do_get(filename)
        elif data[0] == 'P':
            filename = data.split(' ')[-1]
            ftp.do_put(filename)


# 网络搭建
def main():
    #  创建套接字
    sockfd = socket()
    sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    sockfd.bind(ADDR)
    sockfd.listen(5)
    print("Listen the port 8080...")
    while True:
        try:
            connfd, addr = sockfd.accept()
        except KeyboardInterrupt:
            print("退出服务程序")
            return
        except Exception as e:
            print(e)
            continue
        print("链接的客户端:", addr)
        #  创建线程处理请求
        client = Thread(target=handle, args=(connfd,))
        client.setDaemon(True)
        client.start()


if __name__ == "__main__":
    main()

client

from socket import *
import sys
import time


# 具体功能
class FtpClient:
def __init__(self, sockfd):
self.sockfd = sockfd

def do_list(self):
self.sockfd.send(b'L') # 发送请求
# 等待回复
data = self.sockfd.recv(128).decode()
#  ok表示请求成功
if data == 'OK':
#  接收文件列表
data = self.sockfd.recv(4096)
print(data.decode())
else:
print(data)

def do_quit(self):
self.sockfd.send(b'Q')
self.sockfd.close()
sys.exit("谢谢使用")

def do_get(self, filename):
#  发送请求
self.sockfd.send(('G ' + filename).encode())
#  等待回复
data = self.sockfd.recv(128).decode()
if data == 'OK':
fd = open(filename, 'wb')
#  接收内容写入文件
while True:
data = self.sockfd.recv(1024)
if data == b'##':
break
fd.write(data)
fd.close()
else:
print(data)

def do_put(self, filename):
try:
f = open(filename, 'rb')
except Exception:
print("没有该文件")
return

#  发送请求
filename = filename.split('/')[-1]
self.sockfd.send(('P ' + filename).encode())
#  等待回复
data = self.sockfd.recv(128).decode()
if data == 'OK':
while True:
data = f.read(1024)
if not data:
time.sleep(0.1)
self.sockfd.send(b'##')
break
self.sockfd.send(data)
f.close()
else:
print(data)


#  发起请求
def request(sockfd):
ftp = FtpClient(sockfd)

while True:
print("\n==========命令选项===========")
print("*********** list ************")
print("********* get file *********")
print("********* put file *********")
print("*********** quit ************")
print("==============================")

cmd = input("输入命令:")
if cmd.strip() == 'list':
ftp.do_list()
elif cmd.strip() == 'quit':
ftp.do_quit()
elif cmd[:3] == 'get':
filename = cmd.strip().split(' ')[-1]
ftp.do_get(filename)
elif cmd[:3] == 'put':
filename = cmd.strip().split(' ')[-1]
ftp.do_put(filename)


#  网络链接
def main():
#  服务器地址
ADDR = ('127.0.0.1', 8080)
sockfd = socket()
try:
sockfd.connect(ADDR)
except Exception as e:
print("链接服务器失败")
return
else:
print("""
************************
Data File Image
************************
""")
cls = input("请选择文件种类:")
if cls not in ['Data', 'File', 'Image']:
print("Sorry input Error!!")
return
else:
sockfd.send(cls.encode())
request(sockfd) # 发送具体请求


if __name__ == "__main__":
main()
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇