基于套接字通信的简单练习(FTP)
本项目基于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)的更多相关文章
- QT下UDP套接字通信——QUdpSocket 简单使用
QT下UDP套接字通信--QUdpSocket QUdpSocket类提供一个UDP套接字. UDP(用户数据报协议)是一种轻量级.不可靠.面向数据报.无连接的协议.它可以在可靠性不重要的情况下使用. ...
- Python之路(第三十一篇) 网络编程:简单的tcp套接字通信、粘包现象
一.简单的tcp套接字通信 套接字通信的一般流程 服务端 server = socket() #创建服务器套接字 server.bind() #把地址绑定到套接字,网络地址加端口 server.lis ...
- 网络编程 - 1.简单的套接字通信/2.加上通信循环/3.bug修复/4.加上链接循环/5.模拟ssh远程执行命令
1.简单的套接字通信 服务端 ''' 服务端 接电话 客户端 打电话 1.先启动服务端 2.服务端有两种套接字 1.phone 用来干接收链接的 2.conn 用来干收发消息的 ''' import ...
- Python 37 基于多线程实现套接字 、gevent 、单线程下实现并发的套接字通信
一:基于多线程实现套接字 可添加多个客户端 from socket import * from threading import Thread def comunicate(conn): while ...
- python 之 网络编程(基于TCP协议的套接字通信操作)
第八章网络编程 8.1 基于TCP协议的套接字通信 服务端套接字函数 s.bind() 绑定(主机,端口号)到套接字 s.listen() 开始TCP监听 s.accept() 被动接受TCP客户的连 ...
- 什么是 socket?简述基于 tcp 协议的套接字通信流程?
Socket的英文原义是"孔"或"插座".通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄, 可以用来实现不同虚拟机或不同计 ...
- python 之 网络编程(基于UDP协议的套接字通信)
8.5 基于UDP协议的套接字通信 UDP协议:数据报协议 特点:无连接,一发对应一收,先启动哪一端都不会报错 优点:发送效率高,但有效传输的数据量最多为500bytes 缺点:不可靠:发送数据,无需 ...
- python 并发编程 基于gevent模块 协程池 实现并发的套接字通信
基于协程池 实现并发的套接字通信 客户端: from socket import * client = socket(AF_INET, SOCK_STREAM) client.connect(('12 ...
- IPC——流套接字通信
Linux进程间通信——使用流套接字 前面说到的进程间的通信,所通信的进程都是在同一台计算机上的,而使用socket进行通信的进程可以是同一台计算机的进程,也是可以是通过网络连接起来的不同计算机上的进 ...
随机推荐
- Vue通过input筛选数据
<div id="app"> <input v-model='search' /> <ul> <li v-for="item i ...
- C++Builder编写计算器
用C++Builder确实能快速上手, 只要是会一点C++基础的,都能很快的编写一些小程序,而且VCL库组件也很丰富,比微软MFC强多了. 自己动手写了一个计算器来增加自己的兴趣.C++基础以后有空还 ...
- SQL Server遍历所有表统计行数
DECLARE CountTableRecords CURSOR READ_ONLY FOR SELECT sst.name, Schema_name(sst.schema_id) FROM sys. ...
- mybatis关联集合List&分布查询传递多列值
场景:查询部门的同时,要求查询此部门下的所有用户. 部门(Department) private Integer id; private String departmentName; private ...
- 一款css3的标签动画效果
/*响应式设计,动画效果需引入animate.min.css库*/ <div class="index_tag"> <div class="rowFlu ...
- Android杀死进程方法
1. android.os.Process.killProcess(pid) 只能终止本程序的进程,无法终止其它的 具体代码如下: ?12 Process.killProcess(Process.my ...
- WinCE下的串口通信开发(VS2005,VB.Net,VC++)
WinCE下的串口通信开发(VS2005,VB.Net,VC++) WinCE下的串口通信开发 一.利用Visual Basic 开发很简单,因为有现成的控件可以直接调用 以VS2005为例,首先 ...
- STM32之定时器输入捕获
1.输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32的定时器,除了TIM6和TIM7,其他定时器都有输入捕获功能.STM32的输入捕获,简单的说就是通过检测TIMx_CHx上的边沿信号,在边沿 ...
- String.Format() 方法
一 定义 String.Format() 是将指定的 String类型的数据中的每个格式项替换为相应对象的值的文本等效项. string p1 = "Jackie"; string ...
- chromium之observer_list
典型用法如下 /////////////////////////////////////////////////////////////////////////////// // // OVERVIE ...