本项目基于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. xalan\xalan\2.7.2\xercesImpl.jar (系统找不到指定的文件)问题

    本文转自:http://blog.csdn.net/lveliu/article/details/77772828 环境搭建为:maven+tomcat tomcat 8.5.2 以上会出现改问题(包 ...

  2. UVa 10820 - Send a Table(欧拉函数)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  3. C/C++心得-理解指针

    上一篇笔者用自己那不是怎么好理解的逻辑介绍了内存和C中的基本数据类型,现在笔者再根据自己重新所学来说说C语言中的指针. 理解指针才能真正的算C语言入门.也许是我大学期间太关注前端UE,也许是当初开始学 ...

  4. caffe 学习(3)——Layer Catalogue

    layer是建模和计算的基本单元. caffe的目录包含各种state-of-the-art model的layers. 为了创建一个caffe model,我们需要定义模型架构在一个protocol ...

  5. Flex布局(一)flex-direction

    采用Flex布局的元素,被称为Flex容器(flex container),简称"容器".其所有子元素自动成为容器成员,成为Flex项目(Flex item),简称"项目 ...

  6. 关于SQL优化这些你了解吗?

    目录树 背景 优化点 前提必备知识 优化之一 - 从数据库设计方面考虑 优化之二 - 从SQL语句优化方面考虑 优化之三 - 读写分离与分库分表 背景 在当今这个互联网的时代无非要解决两大难题,其一是 ...

  7. 学习笔记(2)centos7 下安装mysql

    centos7安装mysql 本文通过yum方式安装mysql 1.添加mysql yum 仓库 去mysql开发者中心(http://dev.mysql.com/downloads/repo/yum ...

  8. 『ACM C++』HDU杭电OJ | 1416 - Gizilch (DFS - 深度优先搜索入门)

    从周三课开始总算轻松了点,下午能在宿舍研究点题目啥的打一打,还好,刚开学的课程还算跟得上,刚开学的这些课程也是复习以前学过的知识,下半学期也不敢太划水了,被各种人寄予厚望之后瑟瑟发抖,只能努力前行了~ ...

  9. centos7.3上编译安装percona5.7.18

    一,删除操作系统自带mariadb yum remove mariadb 二,下载需要的安装包 percona-toolkit-3.0.3-1.el7.x86_64.rpm boost_1_59_0. ...

  10. easyui datagrid 异步加载数据时滚动条有时会自动滚到最底部的问题

    在使用easyui 的datagrid异步加载数据时发现滚动条有时会自动滚到最底部.经测试发现,如果加载数据前没有选中行则不会出现这个问题.这样我们可以在重新异步加载数据前取消选中行就可以避免这个问题 ...