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
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()
执行需先执行服务端后再执行客户端