基于socketsever下实现的FTP
# ### 客户端client
import socket
import json
import struct
import os sk = socket.socket()
sk.connect( ("127.0.0.1" , 9000) ) def myrecv(info_len = 1024,sign=False):
# 要考虑黏包
if sign:
# (1) 先接受发送数据的实际长度
info_len = sk.recv(4) #
# unpack 返回的是元组(1999,)
info_len = struct.unpack("i",info_len)[0] # (2) 接受服务端返回的数据
file_info = sk.recv(info_len).decode() #
file_dic = json.loads(file_info)
return file_dic # 处理收发数据的逻辑
def auth(opt):
"""
opt: login 登录 or register 注册
"""
usr = input("username: ").strip()
pwd = input("password: ").strip()
dic = {"user":usr,"pwd":pwd,"operate":opt}
str_dic = json.dumps(dic)
# 把数据发送给服务端
sk.send(str_dic.encode())
return myrecv() # 1.注册
# res = auth("register")
# print(res) def register():
res = auth("register")
return res # 2.登录
# res = auth("login")
# print(res)
def login():
res = auth("login")
return res # 3.退出
def myexit():
opt_dic = {"operate":"myexit"}
sk.send(json.dumps(opt_dic).encode())
exit("欢迎下次再来 ... ")
# myexit() # 4.下载
def download():
operate_dict = {
"operate":"download",
"filename":"ceshivideo.mp4"
} opt_str = json.dumps(operate_dict)
sk.send(opt_str.encode("utf-8")) # (1) 为了避免黏包,接受两次数据
res = myrecv(sign=True)
print(res) # {'result': True, 'info': '改文件存在'}
if res["result"]:
# 创建文件夹
try:
os.mkdir("mydownload")
except:
pass # (2) 接受文件名字 和 文件大小
dic = myrecv(sign=True)
print(dic,"<2>") # {'filename': 'ceshivideo.mp4', 'filesize': 54822153} <2> # (3) 接受文件数据
with open("./mydownload/" + dic["filename"],mode="wb") as fp:
while dic["filesize"]:
content = sk.recv(1024)
fp.write(content)
dic["filesize"] -= len(content)
print("客户端下载完毕")
else:
print("文件不存在") # 第一套界面
operate_lst1 = [ ("登录",login) , ("注册",register) ,("退出",myexit)]
# 第二套界面
operate_lst2 = [("下载",download),("退出",myexit)]
"""
( 1, ('登录', <function login at 0x00000234890402F0>) )
(2, ('注册', <function register at 0x0000023489040268>))
(3, ('退出', <function myexit at 0x0000023489040378>))
"""
def main(operate_lst):
for i,tup in enumerate(operate_lst,start=1):
print(i,tup[0]) num = int(input("请选择要执行的号码:>>>").strip())
# 调用函数
res = operate_lst[num-1][1]() # login()
# 返回结果
return res # 循环调用1号操作界面
while True:
# 开启第一套操作界面
res = main(operate_lst1)
print(res)
# 开启第二套操作界面
if res["result"]:
while True:
res = main(operate_lst2)
print(res) sk.close()
# ### 服务端 server
import socketserver
import json
import os
import hashlib
import struct # print(os.getcwd())
print(__file__)
print(os.path.dirname(__file__))
base_path = os.path.dirname(__file__) # 获取当前账户文件所在的完整绝对路径
userinfo = os.path.join(base_path,"db","userinfo.txt")
print(userinfo)
""""""
class Auth(): @staticmethod
def md5(usr,pwd):
md5_obj = hashlib.md5(usr.encode())
md5_obj.update(pwd.encode())
return md5_obj.hexdigest() # 注册
@classmethod
def register(cls,opt_dic) :
# opt_dic = {'user': 'lisi', 'pwd': '222', 'operate': 'register'}
# 1.监测数据库当中是否存在该用户
with open(userinfo,mode="r",encoding="utf-8") as fp:
for line in fp:
username = line.split(":")[0]
if username == opt_dic["user"]:
return {"result":False,"info":"用户名已经存在了"} # 2.当前这个用户允许注册
with open(userinfo,mode="a+",encoding="utf-8") as fp:
# 用户名:密码 换行
fp.write("%s:%s\n" % (opt_dic["user"] , cls.md5(opt_dic["user"],opt_dic["pwd"]))) """
当用户上传文件的时候,动态给用户创建文件夹
""" # 3.直接返回对应的状态
return {"result":True,"info":"注册成功"} # 登录
@classmethod
def login(cls,opt_dic):
# opt_dic = {'user': 'lisi', 'pwd': '222', 'operate': 'register'}
with open(userinfo,mode="r",encoding="utf-8") as fp:
for line in fp:
username,password = line.strip().split(":")
if username == opt_dic["user"] and password == cls.md5(opt_dic["user"],opt_dic["pwd"]):
return {"result":True,"info":"登陆成功"}
return {"result":False,"info":"登录失败"} # 退出
@classmethod
def myexit(cls,opt_dic):
return {"result":"myexit"} class FTPServer(socketserver.BaseRequestHandler):
def handle(self):
while True:
# 接受服务端发送过来的数据
opt_dic = self.myrecv()
print(opt_dic) # 判断类当中是否含有register这个方法,如果有就反射
if hasattr(Auth,opt_dic["operate"]):
# getattr 反射出对应的register函数
res = getattr(Auth,opt_dic["operate"])(opt_dic) # 判断是myexit,代表退出
if res["result"] == "myexit":
return # 把返回值发送给客户端
self.mysend(res) # 等待处理用户第二套操作界面的逻辑
if res["result"]:
while True:
opt_dic = self.myrecv()
print(opt_dic) # 如果operate接受的是myexit 直接终止handle函数;
if opt_dic["operate"] == "myexit":
return # 可以反射 类 或者 对象 或者 模块响应的属性和方法
if hasattr(self,opt_dic["operate"]):
getattr(self,opt_dic["operate"])(opt_dic) # 如果Auth当中没有该操作的应急处理
else:
dic = {"result":False,"info":"没有该操作"}
self.mysend(dic) # 接受数据的方法
def myrecv(self):
info = self.request.recv(1024)
opt_str = info.decode()
opt_dic = json.loads(opt_str)
return opt_dic # 发送数据的方法
def mysend(self,send_info,sign=False):
# 先把字典变成字符串,然后变成字节流发送出去
send_info = json.dumps(send_info).encode() # 增加代码
if sign:
# 通过pack转化成居右固定4个字节长度的字节流
res = struct.pack("i",len(send_info))
# 把接下来要发送的数据长度发送给客户端
self.request.send(res) # # 发送出去
self.request.send(send_info) # # 下载方法
def download(self,opt_dic):
# {'operate': 'download', 'filename': 'ceshivideo.mp4'}
# print(opt_dic)
# 先判断是否存在该文件
filename = opt_dic["filename"]
file_abs = os.path.join(base_path,"myvideo",filename)
# print(filename) # ceshivideo.mp4
# print(file_abs) # D:/gongxiang8/day31/ftp\myvideo\ceshivideo.mp4 if os.path.exists(file_abs):
# 1.先告诉用户,可以操作,存在该文件
dic = {"result":True,"info":"改文件存在"}
self.mysend(dic,sign=True) # 2.把对应的文件名,以及文件的大小发过去
filesize = os.path.getsize(file_abs)
dic = {"filename":filename,"filesize":filesize}
self.mysend(dic,sign=True) # 3.真正开始发送文件内容
with open(file_abs,mode="rb") as fp:
while filesize:
# 一次性最多读取1024个字节
content = fp.read(1024)
self.request.send(content)
filesize -= len(content)
print("服务器下载完毕") else:
dic = {"result":False,"info":"改文件不存在"}
self.mysend(dic,True) myserver = socketserver.ThreadingTCPServer( ("127.0.0.1" , 9000) , FTPServer)
# 让一个端口绑定多个程序(测试时使用)
socketserver.TCPServer.allow_reuse_address = True
myserver.serve_forever()
基于socketsever下实现的FTP的更多相关文章
- 技术的正宗与野路子 c#, AOP动态代理实现动态权限控制(一) 探索基于.NET下实现一句话木马之asmx篇 asp.net core 系列 9 环境(Development、Staging 、Production)
黄衫女子的武功似乎与周芷若乃是一路,飘忽灵动,变幻无方,但举手抬足之间却是正而不邪,如说周芷若形似鬼魅,那黄衫女子便是态拟神仙. 这段描写出自<倚天屠龙记>第三十八回. “九阴神抓”本是& ...
- 基于SourceTree 下的 Git Flow 模型
基于SourceTree 下的 Git Flow 模型 1. sourceTree 是一个开源的git 图形管理工具,可下载mac版本,windows版本 2. Git Flow 是一套使用Git进 ...
- 基于SpringMVC下的Rest服务框架搭建【1、集成Swagger】
基于SpringMVC下的Rest服务框架搭建[1.集成Swagger] 1.需求背景 SpringMVC本身就可以开发出基于rest风格的服务,通过简单的配置,即可快速开发出一个可供客户端调用的re ...
- 团队软件开发_基于windows下截屏软件关于NABC框架的特点
经过我们小组数次的激烈讨论,就自己的能力和时间而言,我们小组的初步的计划是开发一款基于windows下的截图软件. 关于这个软件的功能,我们初步的想法如下: 1.能在windows下后台运行,有相应的 ...
- 1 Linux平台下快速搭建FTP服务器 win7下如何建立ftp服务器
百度经验连接(亲测可用) http://jingyan.baidu.com/article/380abd0a77ae041d90192cf4.html win7下如何建立ftp服务器 http://j ...
- Linux下如何进行FTP安装与设置
1. 先用rpm -qa| grep vsftpd命令检查是否已经安装,如果ftp没有安装,使用yum -y install vsftpd 安装,(ubuntu 下使用apt-get instal ...
- 基于定位下拉框或者需要点击link才显示的下拉框,二次定位与多次定位实现的实际效果区别
还是基于上次那个练习的后续出现的思考,http://www.cnblogs.com/8013-cmf/p/6555790.html 界面: 源码: 写法如下: 继续解释这两种的区别: 1.其实基于定 ...
- 基于Windows下处理Java错误:编码GBK的不可映射字符的解决方案
基于Windows下处理Java错误:编码GBK的不可映射字符的解决方案 最近在研究Java,涉及命令行编译,使用notepad++编辑器,然后使用javac编译: 之前的几个文件没有中文的内容,都没 ...
- 基于Windows下浏览器无法正常打开的解决方案
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable ...
随机推荐
- 剑指offer笔记面试题14----剪绳子
题目:给你一根长度为n的绳子,请把绳子剪成m段(m,n都是整数,n > 1 并且m > 1),每段绳子的长度记为k[0], k[1], ...k[m].请问k[0] x k[1] x .. ...
- vue小案例--简易评论区
一.小案例(评论区) 1.流程 (1)分析静态页面.(vue项目创建参考https://www.cnblogs.com/l-y-h/p/11241503.html)(2)拆分静态页面,变成一个个组件. ...
- JS基础语法---内置对象
js学习中三种对象: 内置对象----js系统自带的对象 自定义对象---自己定义的构造函数创建的对象 浏览器对象---BOM的时候讲 内置对象: Math Date String Array Obj ...
- vue-cli 引用elementUI打包后文件过大
解决方案:使用externals引用第三方资源,防止element资源被打包到自己项目中,(总共修改3个页面index.html.webpack.base.conf.js.main.js) 1.修改i ...
- 配置linux 防火墙,只有固定IP和端口才能能访问完美解决
//添加开放的端口和固定ip vi /etc/sysconfig/iptables [root@root220156 /]# echo "unset MAILCHECK"> ...
- Thymeleaf常用语法:数据延迟加载
在处理模板时,可以由模板逻辑决定是否加载数据,以提高性能.在Spring Boot控制器中设置数据时,使用LazyContextVariable可以实现这功能. 开发环境:IntelliJ IDEA ...
- Spring Boot 2 单元测试
开发环境:IntelliJ IDEA 2019.2.2Spring Boot版本:2.1.8 IDEA新建一个Spring Boot项目后,pom.xml默认包含了Web应用和单元测试两个依赖包.如下 ...
- Linux命令(自己工作常用)
添加用户--root角色才有权限 useradd -d主目录 -m username useradd -d /home/hadoop2 -m hadoop2; 删除用户 userdel -f user ...
- [配置]VUE中通过process.env判断开发,测试和生产环境,并分环境配置不同的URL HOST
本文链接:https://blog.csdn.net/tom_wong666/article/details/89763620 Tom哥的博客博文分类和索引页面地址:https://blog.csdn ...
- HTML网页自动跳转(重定向)
HTML网页自动跳转(重定向) meta <head> <meta http-equiv="refresh" content="5;url=https: ...