本项目基于c/s架构开发(采用套接字通信,使用TCP协议)

FTP-Socket
"""
__author:rianley cheng
""" 功能说明:
本程序是一个模拟 FTP 的应用,包括客户端和服务端,实现如下功能: 1 可以实现多客户端连接, 服务端采用 SocketServer 模块实现,支持多客户端连接 2 实现客户端登录验证, 对客户端登录时采用 sha224 加密算法进行加密, 3 对用户访问目录进行限制,只允许在自己家目录下进行访问,不能进入其他用户目录 4 对用户上传目录磁盘进行限制,支持不同用户定义不同大小,默认500M (此处有服务端进行分配) 5 用户注册放到了服务端进行(客户端无法注册用户) 6 支持上传文件夹 and 文件 7 文件校验比对(主要是 将文件的名称,大小 进行混淆,来确定文件收发的完整性) 8 支持文件上传、下载的进度显示 9 支持以下命令功能
put: 上传文件
get: 下载文件
show: 显示文件夹内容
cd: 目录切换 10 支持断点续传,分片上传。(同时间只有一个·生成器·在内存(客户端 服务端都是如此)) ,不断的收发数据 (优化内存) 11 全局日志记录
目录介绍: client:
|--start.py (主引导程序文件)
|
|--bin (主接口文件目录)
| |-- ftpclient.py (主接口文件,登录接口、调用命令模块主文件)
|
|--conf (配置文件目录)
| |-- codes.py (状态码文件)
| |-- settings.py (系统配置主文件)
| |-- tempate.py (模板文件)
|
|--download (文件下载存放目录)
|
|--logs (日志目录)
| |-- ftpclient.log
|
|--module (模块目录)
| |-- common.py (公共模块)
| |-- client.py (客户端类文件,定义客户端所有命令的方法) ----------------------------------------------------------------------------------- servr:
|--start.py (主引导程序文件)
|
|--bin (主接口文件目录)
| |-- ftpserver.py (主接口文件,登录接口、调用命令模块主文件)
|
|--conf (配置文件目录)
| |-- settings.py (系统配置主文件)
| |-- tempate.py (模板文件)
|
|-- database (数据保存文件)
| |-- breakpoint (断点续传记录文件保存目录,每个用户一个文件)
| |-- user.ini (用户信息保存文件)
|
|-- dbhelper
| |-- dbapi.py (数据操作接口)
|
|--upload (用户上传文件存放目录,下面存放所有用户的家目录,一个用户一个文件夹)
|
|--logs (日志目录)
| |-- ftpclient.log
|
|--module (模块目录)
| |-- common.py (公共模块)
| |-- server.py (服务端模块文件,定义服务端所有命令的方法)
| |-- users.py (用户类文件,每个客户端连接后会生成一个用户对象,这个类文件用来实例化用户对象) 应用关键模块及知识点:
1 模块: socket, socketserver, hashlib(md5,sha224),mutilprocess 2 知识点: 多进程、反射、类、套接字通信、模块的综合使用 项目主要接口关系图:


项目运行截图:

项目核心点介绍以及出现的问题介绍:
第一版,文件夹上传,原本是通过遍历文件中子文件,子子文件,将文件路径存一个列表,将具体文件存一个列表 先传文件夹 (在服务端把具体的文件夹层次关系建立好!)在传文件 将文件内容拿到 往他们对应的文件夹中写入。
但是 出了一个bug(暂无解决) 有的时候 可以 有的时候不行。于是我换用了方式二: 第二版 文件夹上传 采用打包的方式(将文件夹打包,传文件包过去),服务端在接收到文件包后,采用解压文件包的形式。客户端在数据传输完毕 ,删除打包文件,服务端解压文件包完成后。删除文件包。(判断标准是文件夹上传带一个参数is_file ='1',来标识,用户上传的是文件夹还是文件!) 断点续传:采用seek方式 在服务端接收数据 出现客户端异常中断! 将保留原始数据,且记录该用户续传的信息
def write_breakpoint(filemd5, filesize, recved_size, filepath, userobj):
"""
写断点文件信息,每个用户的断点文件信息保存在各自用户的家目录下
:param filesize: 文件总大小
:param filemd5: 文件的MD5值
:param recved_size: 已接收大小
:param filepath: 文件存放路径,全名 ex: uploads/test/aaa.txt
:param userobj: 客户端用户对象
:return: 写文件,格式为{"filemd5":{"filepath":filepath,"recvsize":recved_size,"totalsize":totalsize}}
"""
breadpoint_file = os.path.join(settings.BREAK_POINT_FOLDER, userobj.username)
bfile = {filemd5: {"filepath": filepath, "totalsize": filesize, "recvsize": recved_size}}
# 将信息写入文件
with open(breadpoint_file, 'w+') as fw:
fw.write(json.dumps(bfile))

服务端记录之后:

客户端在上传同名文件,会先传头部信息。服务端验证,是否存在续传,如果存在,返回一个seek值。
客户端在传的时候 ,会判断是否存在续传,存在提示用户,该文件断点续传,在发送数据时 则在传的过程中加上服务端续传过来的位置!seek让文件光标跳转到已上传位置,进行续传
            if str(ack_by_server, encoding='utf-8').split("|")[0] == "0":
# 新文件
sended_size = 0
# 判断文件是否超过磁盘配额空间
if self.usedspace + fsize > self.totalspace:
return "超过磁盘配额,无法上传文件,请联系管理员!"
else:
self.usedspace += fsize
else:
sended_size = int(str(ack_by_server, encoding='utf-8').split("|")[1])
print("此文件已发送过,但未发送完,开始断点续传!......") # 开始发送文件
try:
with open(file_name, 'rb') as f:
f.seek(sended_size) #服务端传过来断点续传文件的值(如果该文件没有存在断点续传,该值为零,则不是断点续传文件)
while fsize - sended_size > 2048:
contant = f.read(2048)
r_size = len(contant)
self.socket.send(contant)
sended_size += r_size
#调用进度条函数
common.print_process(fsize, sended_size)
else:
contant = f.read(fsize - sended_size)
self.socket.send(contant)
#调用进度条函数
common.print_process(fsize, fsize) common.writelog("upload file<{0}> successful".format(file_name), "info")
return "\n文件发送成功"

  

写的比较low,需要FTP源码的小伙伴,关注我博客,下方评论。送上源码。。。

												

基于套接字通信的简单练习(FTP)的更多相关文章

  1. QT下UDP套接字通信——QUdpSocket 简单使用

    QT下UDP套接字通信--QUdpSocket QUdpSocket类提供一个UDP套接字. UDP(用户数据报协议)是一种轻量级.不可靠.面向数据报.无连接的协议.它可以在可靠性不重要的情况下使用. ...

  2. Python之路(第三十一篇) 网络编程:简单的tcp套接字通信、粘包现象

    一.简单的tcp套接字通信 套接字通信的一般流程 服务端 server = socket() #创建服务器套接字 server.bind() #把地址绑定到套接字,网络地址加端口 server.lis ...

  3. 网络编程 - 1.简单的套接字通信/2.加上通信循环/3.bug修复/4.加上链接循环/5.模拟ssh远程执行命令

    1.简单的套接字通信 服务端 ''' 服务端 接电话 客户端 打电话 1.先启动服务端 2.服务端有两种套接字 1.phone 用来干接收链接的 2.conn 用来干收发消息的 ''' import ...

  4. Python 37 基于多线程实现套接字 、gevent 、单线程下实现并发的套接字通信

    一:基于多线程实现套接字 可添加多个客户端 from socket import * from threading import Thread def comunicate(conn): while ...

  5. python 之 网络编程(基于TCP协议的套接字通信操作)

    第八章网络编程 8.1 基于TCP协议的套接字通信 服务端套接字函数 s.bind() 绑定(主机,端口号)到套接字 s.listen() 开始TCP监听 s.accept() 被动接受TCP客户的连 ...

  6. 什么是 socket?简述基于 tcp 协议的套接字通信流程?

    Socket的英文原义是"孔"或"插座".通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄, 可以用来实现不同虚拟机或不同计 ...

  7. python 之 网络编程(基于UDP协议的套接字通信)

    8.5 基于UDP协议的套接字通信 UDP协议:数据报协议 特点:无连接,一发对应一收,先启动哪一端都不会报错 优点:发送效率高,但有效传输的数据量最多为500bytes 缺点:不可靠:发送数据,无需 ...

  8. python 并发编程 基于gevent模块 协程池 实现并发的套接字通信

    基于协程池 实现并发的套接字通信 客户端: from socket import * client = socket(AF_INET, SOCK_STREAM) client.connect(('12 ...

  9. IPC——流套接字通信

    Linux进程间通信——使用流套接字 前面说到的进程间的通信,所通信的进程都是在同一台计算机上的,而使用socket进行通信的进程可以是同一台计算机的进程,也是可以是通过网络连接起来的不同计算机上的进 ...

随机推荐

  1. [转] 从此不再惧怕URI编码:JavaScript及C# URI编码详解

    混乱的URI编码 JavaScript中编码有三种方法:escape.encodeURI.encodeURIComponent C#中编码主要方法:HttpUtility.UrlEncode.Serv ...

  2. 在Mac终端中使用vim编辑文件步骤

    VIM (Unix及类Unix系统文本编辑器) Vim是一个类似于Vi的著名的功能强大.高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性.VIM是纯粹的自由软件. http://jingya ...

  3. 解决SVN UUID客户端和服务器不一致的问题

    下面是从别的文章中COPY过来的两篇文章,可以完美的解决这个问题: 一. 重新定位SVN的时候,遇到uuid不一致的问题. Google得知可以使用以下命令 有到svnadmin命令:(位于 SVN安 ...

  4. Gradle Goodness: Task Output Annotations Create Directory Automatically

    Gradle Goodness: Task Output Annotations Create Directory Automatically One of the great features of ...

  5. <a>标签跳转到Servelet页面并实现参数的传递

    <a>标签跳转到页面不能通过request.setAttribute()和getAttribute()方法获取参数. <a>标签只能通过request.getParameter ...

  6. 课时53.video标签(掌握)

    这节课来学习一下html5中新增的标签,我们先来看一下,html5中新增了哪些标签? 打开W3school的网页,点击参考手册中的HTML/HTML5标签,有一个按字母顺序排列的标签,但凡标签后面带有 ...

  7. Oracle12C创建用户遇到ora-6509

    引用自:http://blog.itpub.net/29357786/viewspace-1995055/ ORACLE 12C创建用户之ORA-65096 2016年2月25日,一北京北方人瑞教育咨 ...

  8. oracle database 9i/10g/11g 编程艺术 源代码下载

    背景 在找这本书的源码,搜到提供的都是需要C币下载的.比较固执(其实是穷). 在这本书的前言中提到源代码可以在 www.appress.com 上下载. 下面是该书在该网站上的链接: https:// ...

  9. Spring入门第二课:Spring配置Bean的细节

    1.配置bean的作用域: 通过配置scope属性可以bean的作用域,参数有 prototype.request.session.singleton. 1)singleton为单例,IoC容器只会创 ...

  10. 竞赛题解 - [CF 1080D]Olya and magical square

    Olya and magical square - 竞赛题解 借鉴了一下神犇tly的博客QwQ(还是打一下广告) 终于弄懂了 Codeforces 传送门 『题目』(直接上翻译了) 给一个边长为 \( ...