"""
ftp 文件服务器
(服务端)
"""
from socket import *
from threading import Thread
import os,time
# 全局变量
HOST='0.0.0.0'
PORT=9898
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("OK".encode())
time.sleep(0.1)
fs=''
for file in files:
# if file[0] != '.':
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")
time.sleep(0.1)
# 发送文件内容
while True:
data=fd.readline(1024)
if not data:
time.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为空,或者发送quit时,退出线程
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():
s=socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(ADDR)
s.listen(5)
print("Listen the port 9898...")
while True:
try:
connfd,addr=s.accept()
except KeyboardInterrupt:
print("退出服务程序")
return
except Exception as e:
print(e)
continue
print("连接的客户端:",addr)
# 创建子线程处理客户端请求
t=Thread(target=handle,args=(connfd,))
t.setDaemon(True)
t.start()
if __name__=="__main__":
main()