ftpFileServer

255 阅读2分钟
<!--ftp_server-->

'''
ftp 文件服务器
fork server训练
socket使用
'''
from socket import *
import os,sys 
import signal
import time

# 全局变量
HOST = '0.0.0.0'
PORT = 8888
ADDR = (HOST,PORT)
# 文件库目录
FILE_PATH = '/home/FTPSERVER/'

# 功能类
class FtpServer(object):
    def __init__(self,connfd):
        self.connfd = connfd


    def do_list(self): 
        # 获取文件列表
        file_list = os.listdir(FILE_PATH)
        if not file_list:
            self.connfd.send("文件库为空".encode())
            return
        else:
            self.connfd.send(b'OK')
            time.sleep(0.1)
        
        files = ''
        for file in file_list:
            if file[0] != '.' and \
                os.path.isfile(FILE_PATH+file):
                files += file + "#"       
        # 将拼接的字符串发送个客户端
        self.connfd.send(files.encode())


    def do_get(self,filename):
        try:
            fd = open(FILE_PATH+filename,'rb')
        except IOError:
            self.connfd.send("文件不存在".encode())
            return
        else:
            self.connfd.send(b'OK')
            time.sleep(0.1)
        # 发送文件
        while True:
            data = fd.read(1024)
            if not data:
                time.sleep(0.1)
                self.connfd.send(b'##')
                break 
            self.connfd.send(data)
        fd.close()


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


# 循环接收请求
def do_requests(connfd):
    ftp = FtpServer(connfd)
    while True:
        data = connfd.recv(1024).decode()            
        if not data  or data[0] == 'Q':
            connfd.close()
            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)

    # 处理僵尸
    signal.signal(signal.SIGCHLD,signal.SIG_IGN)
    print("Listen the port 8888...")

    while True:
        try:
            connfd,addr = sockfd.accept()
        except KeyboardInterrupt:
            sockfd.close()
            sys.exit("服务器退出")
        except Exception as e:
            print('服务器异常:',e)
            continue 
        print("连接客户端:",addr)
        
        # 创建子进程
        pid = os.fork()
        if pid == 0:
            sockfd.close()
            do_requests(connfd) # 处理请求
            os._exit(0)
        else:
            connfd.close()

main()



<!--ftp_client-->

from socket import * 
import sys 
import time

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

# 具体功能
class FtpClient(object):
    def __init__(self,sockfd):
        self.sockfd = sockfd
    
    
    def do_list(self):
        self.sockfd.send(b'L') # 发送请求
        # 等待回复
        data = self.sockfd.recv(128).decode()
        if data == 'OK':
            data = self.sockfd.recv(4096).decode()
            files = data.split('#')
            for file in files:
                print(file)
        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 IOError:
            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 main():
    sockfd = socket()

    try:
        sockfd.connect(ADDR)
    except Exception as e:
        print("连接失败",e)
        return 

    # 创建实例化对象处理文件
    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.split(' ')[-1]
            ftp.do_get(filename)
        elif cmd[:3] == 'put':
            filename = cmd.split(' ')[-1]
            ftp.do_put(filename)
        else:
            print("请输入正确命令")

main()