1. 需求分析
分为服务端和客户端,要求可以有多个客户端同时操作。
客户端可以查看服务器文件库中有什么文件。
客户端可以从文件库中下载文件到本地。
客户端可以上传一个本地文件到文件库。
使用print在客户端打印命令输入提示,引导操作
""
FTP服务器服务端程序
"""
from socket import *
from multiprocessing import Process
from signal import *
import sys
import os
import time
HOST="0.0.0.0"
PORT=8885
ADDR=(HOST,PORT)
DIR = "/home/tarena/month02/day15/"
class FTP_SERVER(Process):
def __init__(self,connfd):
super().__init__(daemon=True)
self.connfd=connfd
def show_FTP_file(self):
file_list=[]
for filename in os.listdir(DIR):
file_list.append(filename)
file_result =" ".join(file_list)
return file_result
def download_file(self,filename):
file=DIR+filename
if not os.path.isfile(filename):
self.connfd.send(b"not found")
else:
self.connfd.send(b"##")
time.sleep(0.1)
with open(file,"rb") as f:
while True:
data=f.read(1024)
if not data:
break
self.connfd.send(data)
time.sleep(0.1) # 防止粘包
self.connfd.send(b"##") #
def upload_file(self):
filename = "%d-%d-%d.txt" % time.localtime()[:3]
with open(filename, 'wb') as f:
while True:
data = self.connfd.recv(1024)
if data == b"##":
break
f.write(data)
self.connfd.send("上传完成".encode())
def run(self):
while True:
try:
data=self.connfd.recv(1024)
if data.decode()=="find":
mege=self.show_FTP_file()
self.connfd.send(mege.encode())
elif data.decode().split(" ")[0]=="download":
filename=data.decode().split(" ")[1]
self.download_file(filename)
elif data.decode().split(" ")[0] == "upload":
self.connfd.send(b"OK")
self.upload_file()
except Exception:
self.connfd.close()
def main():
sock=socket()
sock.bind(ADDR)
sock.listen(5)
print("listen the port %d..."%PORT)
signal(SIGCHLD,SIG_IGN)
while True:
try:
connfd,addr=sock.accept()
print("connect from",addr)
except KeyboardInterrupt:
sock.close()
sys.exit()
p = FTP_SERVER(connfd)
p.start()
if __name__ == '__main__':
main()
"""
FTP客户端程序
"""
from socket import *
import time
import sys
# 服务端地址
ADDR = ("127.0.0.1",8885)
tcp_socket = socket()
tcp_socket.connect(ADDR)
# ------VIEW--------------------
class Ftp_view():
def __init__(self):
self.__ftp_control=Ftp_control()
def display(self):
print("查看服务器内容请输入1")
print("下载服务器文件请输入2")
print("上传服务器内容请输入3")
print("退出服务器客户端请输入4")
def select(self):
number=input("请输入:")
if number=="1":
msg="find"
self.__ftp_control.find_file(msg)
elif number=="2":
msg=input("请输入需要下载的文件名:")
msg1="download "+msg
self.__ftp_control.download_file(msg1,msg)
elif number=="3":
filename = input("File:")
msg1 = "upload " + filename
self.__ftp_control.up_file(msg1,filename)
elif number=="4":
sys.exit("客户端退出")
else:
print("检查输入,重新输入")
def main(self):
while True:
try:
self.display()
self.select()
except Exception:
print("请重新输入")
# ------control--------------------
class Ftp_control():
def find_file(self,msg):
tcp_socket.send(msg.encode())
data = tcp_socket.recv(1024)
print(data.decode().split(" "))
def download_file(self,msg1,msg):
tcp_socket.send(msg1.encode())
data = tcp_socket.recv(1024)
if data.decode()=="not found":
print("输入文件不存在")
return
elif data.decode()=="##":
filename = "%d-%d-%d" % time.localtime()[:3]+msg
with open(filename, 'wb') as f:
while True:
data = tcp_socket.recv(1024)
if data == b"##":
print("下载完成")
break
f.write(data)
def up_file(self,msg1,filename):
tcp_socket.send(msg1.encode())
data = tcp_socket.recv(1024)
if data.decode()=="OK":
with open(filename, 'rb') as f:
while True:
data = f.read(1024)
if not data:
break
tcp_socket.send(data)
time.sleep(0.1)
tcp_socket.send(b"##")
# 接收 “上传完成”
data = tcp_socket.recv(1024)
print(data.decode())
if __name__ == '__main__':
p=Ftp_view()
p.main()