python实现ftp

最近学习python,完成了进程线程的学习,到了用python实现ftp

无奈白天要上班,晚上到家十点多了;只能每天晚上坚持学习一两个小时,进展比较缓慢;工作不忙的时候可以挤时间学习下,忙的时候也没办法继续推进;

 

实现功能:

dir: 获取文件列表

get filename: 下载文件

put filename: 上传文件

cd: 修改工作目录

pwd: 获取文件路径(当前实现了获取绝对路径,相对路径还没实现)

mkdir: 新建一个目录

rmdir: 删除一个目录

quit: 退出

Server端代码: 

#!/usr/bin/python3
#coding:utf-8

import sys,os
import signal
from socket import *
from time import sleep
from multiprocessing import Process

#指定TFTP的目录
TFTP_PATH = '/tmp/'


#定义客户端类,传递connfd,并将处理请求定义为类方法
class client_class(object):
    def __init__(self,connfd,addr):
        self.connfd = connfd
        self.addr = addr

    #处理查看请求
    def dir_file(self):
        print('查看文件',self.addr)
        #将查看的文件导入到.dir隐藏文件中
        file = TFTP_PATH + '.dir'
        command = 'ls -lh {} > {}'.format(TFTP_PATH,file)
        os.system(command)

        #如果指显示文件名的话,则用下面的方式
        #data = os.listdir(TFTP_PATH)

        try:
            f = open(file, 'r')
        except Exception as e:
            print('Error')

        for file in f:
            self.connfd.send(file.encode())
        sleep(0.1)
        self.connfd.send('##'.encode())

    #处理退出请求,打印记录用于审计
    def quit(self):
        self.connfd.close()
        print('断开连接:',self.addr)

    def pwd(self):
        self.connfd.send(os.getcwd().encode())

    def cd_command(self,dirname):
        dir = TFTP_PATH + dirname
        try:
            os.chdir(dir)
            self.connfd.send(b'OK')
        except Exception as e:
            self.connfd.send(b'Failed')

    def rmdir_command(self,dirname):
        dir = TFTP_PATH + dirname
        try:
            os.rmdir(dir)
            self.connfd.send(b'OK')
            print('删除目录',dirname,self.addr)
        except Exception as e:
            self.connfd.send(b'Failed')

    def mkdir_command(self,dirname):
        dir = TFTP_PATH + dirname
        try:
            os.mkdir(dir)
            self.connfd.send(b'OK')
            print('新建目录',dirname,self.addr)
        except Exception as e:
            self.connfd.send(b'Failed')


    #处理下载文件请求
    def get_file(self,filename):
        print('download file:',filename,self.addr)
        file = TFTP_PATH + filename
        #判断打开文件是否成功
        try:
            f = open(file,'rb')
        except Exception as e:
            self.connfd.send(b'FAIL')
        else:
            self.connfd.send(b'OK')
        #防止粘包,sleep
        sleep(0.1)
        #逐行读取文件,并发送
        for line in f:
            self.connfd.send(line)
        sleep(0.1)
        #结尾以##,防止粘包现象
        self.connfd.send('##'.encode())
        f.close()
        print('文件发送完毕',filename, self.addr)


    #处理上传文件请求
    def put_file(self,filename):
        print('上传文件',filename,self.addr)
        file = TFTP_PATH + filename
        try:
            f = open(file,'w')
        except Exception as e:
            print('file open failed',file)
        else:
            while True:
                data = self.connfd.recv(1024).decode()
                if data == '##':
                    break
                f.write(data)
            f.close()


#定义函数,用于处理客户端请求;每个子进程都调用该函数
def client_handler(sockfd):
    try:
        clientfd,addr = sockfd.accept()
    except KeyboardInterrupt:
        print('Quit')
        sys.exit(0)
    except Exception as e:
        print(e)
    print('收到连接:',addr)
    sockfd.close()
    #创建类对象
    client_instance = client_class(clientfd, addr)
    while True:
        data = clientfd.recv(1024)
        data = data.decode()
        print(data)
        if data == 'dir':
            client_instance.dir_file()
        elif data == 'quit':
            client_instance.quit()
            break
        elif data[:3] == 'get':
            filename = data.split(' ')[1]
            client_instance.get_file(filename)
        elif data.split(' ')[0] == 'put':
            filename = data.split(' ')[1]
            client_instance.put_file(filename)
        elif data[:3] == 'pwd':
            client_instance.pwd()
        elif data[:2] == 'cd':
            dirname = data[3:]
            client_instance.cd_command(dirname)
        elif data[:5] == 'rmdir':
            dirname = data[6:]
            client_instance.rmdir_command(dirname)
        elif data[:5] == 'mkdir':
            dirname = data[6:]
            client_instance.mkdir_command(dirname)
        else:
            print('Command Error',client_instance.addr)
        sleep(1)
    clientfd.close()




#主函数
def main():
    HOST = ''
    PORT = 8888
    ADDR = (HOST,PORT)
    sockfd = socket(AF_INET, SOCK_STREAM)
    sockfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    sockfd.bind(ADDR)
    sockfd.listen(5)
    while True:
        signal.signal(signal.SIGCHLD, signal.SIG_IGN)
        p = Process(target=client_handler, args=(sockfd,))
        p.start()
        p.join()


if __name__ == '__main__':
    main()


Client代码

#!/usr/bin/python3
# coding:utf-8

import sys
from socket import *
from time import sleep


# 定义connection_class类,用于封装自定义处理方法
class connection_class(object):
    def __init__(self, connfd):
        self.connfd = connfd

    # 查看列表
    def dir_file(self):
        connfd.send(b'dir')
        while True:
            data = connfd.recv(10000)
            data = data.decode()
            # 如果接收到'##',则说明文件已接收完毕,则退出
            if data == '##':
                break
            print(data)

    # 下载文件
    def get_file(self, filename):
        file = FILE_PATH + filename
        try:
            f = open(file, 'w')
        except IOError:
            print('ERROR', file)
        data = self.connfd.recv(1024)
        data = data.decode()
        if data == 'OK':
            while True:
                data = self.connfd.recv(1024).decode()
                if data == '##':
                    break
                f.write(data)
            f.close()
        else:
            print('download failed!')
        print('文件下载完毕')

    # 上传文件
    def put_file(self, filename):
        file = FILE_PATH + filename
        print(file)
        try:
            f = open(file, 'rb')
        except Exception as e:
            print('上传的文件不存在')
            self.connfd.send('##'.encode())
            return
        else:
            for line in f:
                self.connfd.send(line)
            sleep(0.1)
            self.connfd.send('##'.encode())
            print('文件上传完毕')
            f.close()
    def pwd_command(self):
        data = self.connfd.recv(1024)
        print(data.decode())

    def cd_command(self,dirname):
        data = self.connfd.recv(1024)
        print(data.decode())

    def rmdir(self,dirname):
        data = self.connfd.recv(1024)
        print(data.decode())

    def mkdir(self,dirname):
        data = self.connfd.recv(1024)
        print(data.decode())

# 定义菜单功能
menu = '''
------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------
'''
# 定义目录,选择当前目录
FILE_PATH = './'
connfd = socket(AF_INET, SOCK_STREAM)
ADDR = ('', 8888)
connfd.connect(ADDR)
conn_instance = connection_class(connfd)

# 死循环,以处理请求
while True:
    # 每次打印菜单
    print(menu)
    # 接收命令
    msg = input('>>>')
    # 判断命令的类别: dir,get,put,quit等
    if msg == 'dir':
        conn_instance.dir_file()
    elif msg.split(' ')[0] == 'get':
        connfd.send(msg.encode())
        filename = msg.split(' ')[1]
        print('get file:', filename)
        conn_instance.get_file(filename)
    elif msg.split(' ')[0] == 'put':
        filename = msg.split(' ')[1]
        print('put file:', filename)
        connfd.send(msg.encode())
        conn_instance.put_file(filename)
    elif msg == 'quit':
        connfd.send(b'quit')
        sys.exit(0)
    elif msg == '':
        pass
    elif msg == 'pwd':
        connfd.send(msg.encode())
        conn_instance.pwd_command()
    elif msg[:2] == 'cd':
        dirname = msg[3:]
        print('cd ',dirname)
        connfd.send(msg.encode())
        conn_instance.cd_command(dirname)
    elif msg[:5] == 'rmdir':
        dirname = msg[6:]
        print('rmdir',dirname)
        connfd.send(msg.encode())
        conn_instance.rmdir(dirname)
    elif msg[:5] == 'mkdir':
        dirname = msg[6:]
        print('mkdir',dirname)
        connfd.send(msg.encode())
        conn_instance.mkdir(dirname)

    else:
        print('Error')

执行展示:Server

[root@A02-R05-I18-13-A003335 .coding]# ./server.py 
收到连接: ('127.0.0.1', 6733)
dir
查看文件 ('127.0.0.1', 6733)
put jjjjj
上传文件 jjjjj ('127.0.0.1', 6733)
dir
查看文件 ('127.0.0.1', 6733)
pwd
cd ..
pwd
cd /tmp
cd tmp
dir
查看文件 ('127.0.0.1', 6733)
pwd
cd tmp
cd ../tmp
pwd
dir
查看文件 ('127.0.0.1', 6733)
cd wang
pwd
quit
断开连接: ('127.0.0.1', 6733)
收到连接: ('127.0.0.1', 6762)
quit
断开连接: ('127.0.0.1', 6762)
收到连接: ('127.0.0.1', 6765)
dir
查看文件 ('127.0.0.1', 6765)
quit
断开连接: ('127.0.0.1', 6765)

Client:

[root@A02-R05-I18-13-A003335 .coding]# ./client.py 

------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>   quit
Error

------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>quit
[root@A02-R05-I18-13-A003335 .coding]# ./client.py 

------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>dir
总用量 67M

-rwxr-xr-x 1 root  root    89 8月  22 11:03 3.py
-rw-r--r-- 1 root  root    25 8月  14 20:51 file1.txt
drwxr-xr-x 2 admin admin 4.0K 12月 26 2018 hsperfdata_admin
-rw-r--r-- 1 root  root   67M 8月  15 10:34 jd_sigma_20190814002201.sql
-rw-r--r-- 1 root  root     0 8月  22 11:08 jjjjj
-rw-r--r-- 1 root  root    83 8月  20 17:22 llj
-rw-r--r-- 1 root  root    15 8月  20 17:30 llj.txt
drwxr-xr-x 2 root  root  4.0K 8月  20 21:03 love
-rw-r--r-- 1 root  root  7.0K 8月  20 16:44 mysql_run.err
-rw-r--r-- 1 root  root     4 8月  22 11:05 passwd
srwxr-xr-x 1 root  root     0 8月  13 16:45 s.sock
drwxr-xr-x 2 root  root  4.0K 8月  20 20:06 tftpdir
drwxr-xr-x 2 root  root  4.0K 8月  20 21:00 wang
drwxr-xr-x 2 root  root  4.0K 8月  21 00:09 ww
-rw-r--r-- 1 root  root     3 8月  22 11:05 wwww


------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>get 3.py
get file: 3.py
文件下载完毕

------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>put 3.py
put file: 3.py
./3.py
文件上传完毕

------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>pwd
/tmp/.coding

------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>mkdir llj_love
mkdir llj_love
OK

------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>dir
总用量 67M
-rwxr-xr-x 1 root  root    89 8月  22 11:33 3.py
-rw-r--r-- 1 root  root    25 8月  14 20:51 file1.txt
drwxr-xr-x 2 admin admin 4.0K 12月 26 2018 hsperfdata_admin
-rw-r--r-- 1 root  root   67M 8月  15 10:34 jd_sigma_20190814002201.sql
-rw-r--r-- 1 root  root     0 8月  22 11:08 jjjjj

-rw-r--r-- 1 root  root    83 8月  20 17:22 llj
drwxr-xr-x 2 root  root  4.0K 8月  22 11:33 llj_love
-rw-r--r-- 1 root  root    15 8月  20 17:30 llj.txt
drwxr-xr-x 2 root  root  4.0K 8月  20 21:03 love
-rw-r--r-- 1 root  root  7.0K 8月  20 16:44 mysql_run.err
-rw-r--r-- 1 root  root     4 8月  22 11:05 passwd
srwxr-xr-x 1 root  root     0 8月  13 16:45 s.sock
drwxr-xr-x 2 root  root  4.0K 8月  20 20:06 tftpdir
drwxr-xr-x 2 root  root  4.0K 8月  20 21:00 wang
drwxr-xr-x 2 root  root  4.0K 8月  21 00:09 ww
-rw-r--r-- 1 root  root     3 8月  22 11:05 wwww


------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>rmdir ww      
rmdir ww
OK

------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>cd llj_love
cd  llj_love
OK

------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>pwd
/tmp/llj_love

------------------ dir : get the files list--------------------------
------------------ get filename : download file  --------------------
------------------ put filename : upload file -----------------------
------------------ cd : change the current directory  ---------------
------------------ pwd : print the path  ----------------------------
------------------ mkdir: create a directory-------------------------
------------------ rmdir: remove a directory ------------------------
------------------ quit: exit the client  ---------------------------

>>>quit
[root@A02-R05-I18-13-A003335 .coding]# 

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值