python socket 实现模拟ftp 上传、下载文件

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()

 

你可能感兴趣的:(python基础)