ftp 实现功能如下:
1、实现多用户登陆,需使用用户名密码校验登陆过程
2、每个用户有自己的加目录
3、可使用ls、cd指令切换查看目录
4、可是实现上传下载文件的功能
5、可以断点续传
目前只是简单实现,还存在较多bug
客户端代码
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Author:xianyanghua
# @Time :2019/7/9 10:47
# @File : socket_client.py
# @Software: PyCharm
import struct
from socket import *
import os
import sys
class mysocketClient(object):
def __init__(self,HOST,PORT,dire=None):
self.sock= socket(AF_INET,SOCK_STREAM)
self.sock.connect((HOST,PORT))
self.dire=dire
def start(self):
self.auth()
def auth(self):
while True:
msg=raw_input('请输入用户名密码 username:password >>>')
if msg.count(':')==1:
self.sock.send(msg.encode('utf-8'))
data=self.sock.recv(1024)
if data.startswith('你好'):
username,password=msg.split(':')
self.dire=username
self.interactive()
else:
continue
else:
print('输入格式有误')
continue
def interactive(self):
while True:
print('instruction fuction [filename]')
try:
if not self.dire:
msg = raw_input('>>>>%s '%self.dire)
else:
msg= raw_input('>>>[%s]'%self.dire )
if msg.count(' ')==1:
fuc,filename=msg.split(' ')
print('.........1.........')
print(fuc,filename)
elif not msg:
print('不能为空')
continue
else:
fuc=msg
filename=None
print('2......................')
print(fuc,filename)
if hasattr(self,fuc):
print('...............')
func=getattr(self,fuc)
print(func)
func(filename)
except Exception as e:
print(e)
continue
def push(self,filename):
print(filename)
msg='push '+filename
self.sock.send(msg.encode('utf-8'))
data = self.sock.recv(1024)
print(data)
if data.decode('utf-8') == 'ready':
file_size = os.path.getsize(filename)
print(file_size)
length = struct.pack('i', file_size)
self.sock.send(length)
f = file(filename, 'rb')
send_size = 0
while not file_size == send_size:
if file_size - send_size > 1024:
msg = f.read(1024)
send_size += len(msg)
else: # left data less than 1024
msg = f.read(file_size - send_size)
send_size += (file_size - send_size)
self.sock.send(msg)
per = int((float(send_size) / float(file_size)) * 100)
self.processBar(per)
f.close()
data = self.sock.recv(1024)
if data.decode('utf-8') == 'success':
print('')
self.sock.send('success'.encode('utf-8'))
print('传输完成')
def get(self,filename):
pass
def ls(self,filename):
if not filename:
self.sock.send('ls'.encode('utf-8'))
data=self.sock.recv(1024)
print('[[[[]]]')
print(data)
def cd(self,filename):
if not filename:
print('filename 不能为空')
self.sock.send('cd '+filename)
data=self.sock.recv(1024)
print(data)
if data=='cdSuccess':
self.dire=filename
print(data)
else:
print(data)
def processBar(self,percent):
bar_length = 100
hashes = '#' * int(percent / 100.0 * bar_length)
spaces = ' ' * (bar_length - len(hashes))
sys.stdout.write("\rPercent: [%s] %d%%" % (hashes + spaces, percent))
sys.stdout.flush()
if __name__=='__main__':
HOST='127.0.0.1'
PORT=8003
s1=mysocketClient(HOST,PORT)
s1.start()
服务端代码
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Author:xianyanghua
# @Time :2019/7/16 12:52
# @File : ftpserver.py
# @Software: PyCharm
import socketserver
import os
import sys
import struct
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
try:
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
os.chdir(BASEDIR)
os.chdir('ftpserver')
userconf={'hua': '123', 'liu': '321'}
data=self.request.recv(1024)
user,password=data.split(':')
if userconf[user]==password:
self.request.send('你好'+user+'欢迎登录ftp服务器')
platform=sys.platform
if platform=='win32':
pwd=os.getcwd()
os.chdir('hua')
pwd = os.getcwd()
print(platform,pwd)
else:
self.request.send('用户名密码错误')
self.request.close()
except Exception as e:
print(e)
self.request.close()
try:
while True:
data = self.request.recv(1024)
if not data:
continue
if data=='ls':
data=os.listdir('.')
print( data)
data=str(data)
try:
if data.startswith('cd'):
fuc,filename=data.split(' ')
print(data)
print (fuc,filename)
os.chdir(filename)
data='cdSuccess'
except Exception as e:
print(e)
data=e
if data.startswith('push'):
filename=data.split(' ')[1]
self.request.send('ready')
print('......')
file_size = self.request.recv(4)
file_size=struct.unpack('i',file_size)[0]
print(file_size,',,,,,,,,,,,')
recv_size=0
recv_msg=''
f = file(filename, 'wb')
while not file_size == recv_size: # 只要文件总大小和已收到的大小不想等,就代表还没收完
if file_size - recv_size > 1024: # 文件总大下减已收到的大小等于还剩下没收到的大小,如果这个数大于1024,代表一次肯定收不完,那就还得多循环几次
data = self.request.recv(1024) # 这次收1024字节,但实际上收到的可能比1024小,所以需要以实际收到的数为准
recv_size += len(data) # 已收到的大小加上这一次循环收到的实际大小
else: # 如果最后剩下的少于1024,那就一次性把剩下的都收过来
data = self.request.recv(file_size - recv_size)
# recv_size = file_size #不能这么写,因为这一次依然不一定能一次性收完,因为实际收到的数据可能比你规定的数据要少, 所以需要按下面这行的方式写
recv_size += (file_size - recv_size)
f.write(data)
print(recv_msg)
f.close()
self.request.send('success')
data=self.request.recv(1024)
print(data)
continue
self.request.send(data)
except Exception as e:
print(e)
self.request.close()
print(data)
if __name__=='__main__':
HOST='127.0.0.1'
PORT=8003
server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
server.serve_forever()