服务端代码:程序目录server/server.py   上传文件目录:server/upload

import os
import time
import socket
import selectors #封装了一些相应的操作 BASE_DIR=os.path.dirname(os.path.abspath(__file__)) #第二步:
class selectFtpServer:
def __init__(self):
self.dic = {} #创建空字典
self.hasReceived=0
self.sel = selectors.DefaultSelector() #通过selectors模块下的DefaultSelector这个类拿I/O多路方法拿到实例对象变成实例变量self.sel
self.create_socket() #create_socket()是创建socket对象函数完成绑定功能
self.handle() #handle()函数完成循环监听 #create_socket函数是用来创建socket对象完成绑定功能
def create_socket(self):
server = socket.socket() #创建socket对象赋值server
server.bind(('192.168.1.160', 8080)) #绑定
server.listen(5) #监听
server.setblocking(False) #设置非阻塞
self.sel.register(server, selectors.EVENT_READ,self.accept) #有了server对象通过self.sel实例变量register注册完成绑定功能(server跟self.accept做绑定)
print("服务端已启动,等待客户端连接.....") #handle()函数完成循环监听
def handle(self):
while True: #第一步:程序启动后走while循环 #第七步:运行完accept函数后到这里
#所有操作围绕一个对象self.sel实例变量核心对象展开的
events = self.sel.select() #第二步:调用self.sel实例变量,监听的内容server封装到events对象里 #第八步:如果客户端发过来此刻监听的内容就有变化有俩个对象server和conn封装到events对象里
for key, mask in events: #第三步:for循环events(可迭代对象)拿到key和mask #第九步:for循环events(可迭代对象)拿到key和mask
callback = key.data #第四步:当前key.data是self.accept函数赋值给callback #第十步:当前key.data是read函数赋值给callback
#key.fileobj是拿到的监听的对象。
callback(key.fileobj, mask) #第五步:运行callback执行accpt()函数 #第十一步:运行callback执行read()函数里面放到的之前链接相应的文件描述符conn
#print('当前监听的对象:', key.fileobj) #第六步:accept函数接收连接服务端的客户端信息
def accept(self,sock,mask): #接收sock和mask
conn, addr = sock.accept() #sock.accept接收此时链接服务端的socket对象拿到conn和addr
#print('accepted', conn, 'from', addr)
print("from %s %s connected" %addr)
conn.setblocking(False) #设置成非阻塞
self.sel.register(conn, selectors.EVENT_READ, self.read) #把conn跟read做绑定后程序返回到handle()函数里的events继续监听
#print(conn) self.dic[conn] = {} #在空字典里进行了conn赋值,self.dic={conn:{},} #第十二步:read函数返回给客户端ok
def read(self,conn, mask): #接收了conn和mask
try: #加异常防止客户端突然断开
if not self.dic[conn]: #判断self.dic[conn]里面是否是空字典,如果是空字典,代表第一次进来
data = conn.recv(1024) #conn接收了客户端发来的数据
cmd,filename,filesize = str(data,encoding='utf-8').split('|') #把接收到客户端发来的包解开拿到cmd,filename,filesize个信息
self.dic={conn:{"cmd" : cmd, "filename" : filename, "filesize" : int(filesize)}} #把拿到的cmd,filename,filesize信息放到self.dic字典里去后程序返回到handle()函数里的events继续监听 if cmd == 'put': #如果接收的信息是put
conn.send(bytes("OK",encoding='utf8')) #给客户端返回一条数据 if self.dic[conn]['cmd'] == 'get':
file = os.path.join(BASE_DIR,"upload",filename) if os.path.exists(file):
fileSize = os.path.getsize(file)
send_info = '%s|%s' %('YES',fileSize)
conn.send(bytes(send_info, encoding='utf8'))
else:
send_info = '%s|%s' %('NO',0)
conn.send(bytes(send_info, encoding='utf8')) else: #如果不是空字典代表不是第一次进来
if self.dic[conn].get('cmd',None): #对接收的命令进行分发判断是put还是get
cmd=self.dic[conn].get('cmd')
if hasattr(self, cmd): #如果cmd=put调用put函数,如果是cmd=get函数调用get函数
func = getattr(self,cmd)
func(conn)
else:
print("error cmd!")
conn.close()
else:
print("error cmd!")
conn.close() except Exception as e:
print('断开的客户端信息是:', conn)
self.sel.unregister(conn) #如果没有接收到数据做一个关闭解除
conn.close() #put上传函数
def put(self, conn):
fileName = self.dic[conn]['filename']
fileSize = self.dic[conn]['filesize']
path = os.path.join(BASE_DIR,"upload",fileName) #拿到要接收的信息
#print(fileName,fileSize,path)
recv_data = conn.recv(1024) #接收客户端上传的数据1024字节
self.hasReceived += len(recv_data) #把接收的数据累加到变量self.hasReceived with open(path, 'ab') as f: #打开文件
f.write(recv_data) #把接收的数据写到文件里去 if fileSize == self.hasReceived: #判断文件大小跟接收大小是否一样
if conn in self.dic.keys(): #如果文件大小跟接收大小一样清空字典
self.dic[conn] = {}
print("%s 上传完毕!" %fileName) if __name__=='__main__':
selectFtpServer() #第一步:实例化触发selectFtpServer这个类

客户端代码:目录结果:/client/clenb.py

import socket
import os,sys
BASE_DIR=os.path.dirname(os.path.abspath(__file__)) class selectFtpClient:
def __init__(self):
self.args=sys.argv #sys.argv在命令行输入的参数,第一个参数默认文件名,第二个参数跟IP地址和端口
if len(self.args)>1: #如果大于1把第二个参数俩个值赋值给port
self.port=(self.args[1],int(self.args[2]))
else:
self.port=("192.168.1.160",8080) #如果没有第二个参数默认取这个
self.create_socket() #
self.command_fanout() #进行命令分发 #create_socket函数创建socket对象连接服务端
def create_socket(self):
try:
self.sk = socket.socket()
self.sk.connect(self.port)
print('连接FTP服务器成功!')
except Exception as e:
print("eroor:",e) #command_fanout()函数进行命令分发
def command_fanout(self):
while True:
cmd = input('>>>').strip() #引导用户输入上传还是下载
if cmd == 'exit()':
break
cmd,file = cmd.split() #把输入的命令分开进行反射
if hasattr(self,cmd):
func = getattr(self,cmd)
func(cmd,file)
else:
print('调用错误!') #put()上传函数
def put(self,cmd,file): if os.path.isfile(file): #判断本地文件是否存在
fileName = os.path.basename(file) #取出文件的名字
fileSize = os.path.getsize(file) #取出文件的大小
fileInfo = '%s|%s|%s'%(cmd,fileName,fileSize) #给文件名字大小打包成fileInf
self.sk.send(bytes(fileInfo, encoding='utf8')) #调用send方法把fileInf发给服务端
recvStatus = self.sk.recv(1024) #接收服务端返回的OK内容
print('recvStatus' , recvStatus)
hasSend = 0
if str(recvStatus, encoding='utf8') == "OK": #如果接收到服务端返回的OK
with open(file, 'rb') as f: #打开文件
while fileSize > hasSend : #循环的去上传文件
contant = f.read(1024)
recv_size = len(contant)
self.sk.send(contant)
hasSend += recv_size
s=str(int(hasSend/fileSize*100))+"%"
print("正在上传文件: "+fileName+" 已经上传:" +s)
print('%s文件上传完毕' % (fileName,))
else:
print('文件不存在') #get()下载函数
def get(self,cmd,file):
pass if __name__=='__main__':
selectFtpClient()

python-selctors实现文件上传的更多相关文章

  1. python Django之文件上传

    python Django之文件上传 使用Django框架进行文件上传共分为俩种方式 一.方式一 通过form表单进行文件上传 #=================================== ...

  2. Python 基于Python实现Ftp文件上传,下载

    基于Python实现Ftp文件上传,下载   by:授客 QQ:1033553122 测试环境: Ftp客户端:Windows平台 Ftp服务器:Linux平台 Python版本:Python 2.7 ...

  3. Python Socket实现文件上传(TCP协议)

    在TCP协议下通过socket模块实现文件上传 #!/usr/bin/env python # -*- coding: utf-8 -*- # desc: tcp_server_file_upload ...

  4. selenium+python自动化77-autoit文件上传

    前言 关于非input文件上传,点上传按钮后,这个弹出的windows的控件了,已经跳出三界之外了,不属于selenium的管辖范围(selenium不是万能的,只能操作web上元素).autoit工 ...

  5. selenium+python自动化77-autoit文件上传【转载】

    前言 关于非input文件上传,点上传按钮后,这个弹出的windows的控件了,已经跳出三界之外了,不属于selenium的管辖范围(selenium不是万能的,只能操作web上元素).autoit工 ...

  6. Python学习---网络文件上传

    中心思想: 传递过去文件的大小,根据文件的大小判断是否文件上传完成: 传递/接受文件采用分流的形式,每次传递/接受部分数据:  文件的读取均采用绝对路径实现,而且是bytes的形式读写 客户端: # ...

  7. python模拟浏览器文件上传,csrf放行

    服务器端视图函数 from django.shortcuts import render,HttpResponse from django.views.decorators.csrf import c ...

  8. Python接口自动化——文件上传/下载接口

    〇.前言 文件上传/下载接口与普通接口类似,但是有细微的区别. 如果需要发送文件到服务器,例如:上传文档.图片.视频等,就需要发送二进制数据,上传文件一般使用的都是 Content-Type: mul ...

  9. Selenium2+python自动化75-非input文件上传(SendKeys)

    前言 不少小伙伴问非input标签如何上传文档,这个本身就是一坑,无奈很多小伙伴非要跳坑里去,那就介绍一个非主流的上传文件方法吧,用第三方库SendKeys. 只支持python2环境 python3 ...

  10. python - web自动化测试 - 文件上传操作

    # 12. 上传操作## (1)如果是input可以直接输入路径的,直接使用send_keys输入路径# (2)非input标签的,需要借助第三方工具:# A. AutoIt : 调用其生成的au3或 ...

随机推荐

  1. FlatList 核心运用

    <FlatList data={this.state.stuList} renderItem={this._renderItem} keyExtactor={this._keyExtractor ...

  2. javascript数据基本类型和引用数据类型区别

    基本类型和引用数据类型区别 1.基本数据类型和引用数据类型 javascript中有两种数据类型,分别是基本数据类型和引用数据类型: 基本数据(原始数据)类型指的是简单的数据段,而引用数据类型则指的是 ...

  3. 安装easydict

    在运行lightheadrcnn做test时,提示缺少easydict 不知道什么原因,用pip install easydict或者conda install easydict都没有用,不能安装ea ...

  4. RockerMQ实战之快速入门

    文章目录 RocketMQ 是什么 专业术语 Producer Producer Group Consumer Consumer Group Topic Message Tag Broker Name ...

  5. EFCore Owned Entity Types,彩蛋乎?鸡肋乎?之鸡肋篇

    鸡肋 鸡肋(Chicken ribs),现代汉语词语,出自<三国志·魏书·武帝纪>裴松之注引<九州春秋>曰:"夫鸡肋,弃之如可惜,食之无所得,以比汉中,知王欲还也.& ...

  6. [转]MYSQL 创建存储过程

    MySQL 存储过程是从 MySQL 5.0 开始增加的新功能.存储过程的优点有一箩筐.不过最主要的还是执行效率和SQL 代码封装.特别是 SQL 代码封装功能,如果没有存储过程,在外部程序访问数据库 ...

  7. Problem B: STL——集合运算

    Description 集合的运算就是用给定的集合去指定新的集合.设A和B是集合,则它们的并差交补集分别定义如下: A∪B={x|x∈A∨x∈B} A∩B={x|x∈A∧x∈B} A-B={x|x∈A ...

  8. myeclipse 修改用户名密码

    当在一台公共的电脑上开发程序时,就需要涉及到更改svn用户名和密码,不然直接用本机用户密码提交,有点不妥. win7系统解决方案: C:\Documents and Settings\Administ ...

  9. c++学习过程

    作者本人也是一名初学者,我的QQ:2522929921,可以一起交流啊! 希望广大初学者能够一起进步: 1.掌握编程思维真的很重要!!!!***. 2.不能刻意记忆语法规则. 3.在循序渐进的项目实战 ...

  10. centos 系统上如何把python升级为3

    第一种方式: SCL 源目前由 CentOS SIG 维护,除了重新编译构建 Red Hat 的 Software Collections 外,还额外提供一些它们自己的软件包. 该源中包含不少程序的更 ...