最近学习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]#