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

  1. import os
  2. import time
  3. import socket
  4. import selectors #封装了一些相应的操作
  5.  
  6. BASE_DIR=os.path.dirname(os.path.abspath(__file__))
  7.  
  8. #第二步:
  9. class selectFtpServer:
  10. def __init__(self):
  11. self.dic = {} #创建空字典
  12. self.hasReceived=0
  13. self.sel = selectors.DefaultSelector() #通过selectors模块下的DefaultSelector这个类拿I/O多路方法拿到实例对象变成实例变量self.sel
  14. self.create_socket() #create_socket()是创建socket对象函数完成绑定功能
  15. self.handle() #handle()函数完成循环监听
  16.  
  17. #create_socket函数是用来创建socket对象完成绑定功能
  18. def create_socket(self):
  19. server = socket.socket() #创建socket对象赋值server
  20. server.bind(('192.168.1.160', 8080)) #绑定
  21. server.listen(5) #监听
  22. server.setblocking(False) #设置非阻塞
  23. self.sel.register(server, selectors.EVENT_READ,self.accept) #有了server对象通过self.sel实例变量register注册完成绑定功能(server跟self.accept做绑定)
  24. print("服务端已启动,等待客户端连接.....")
  25.  
  26. #handle()函数完成循环监听
  27. def handle(self):
  28. while True: #第一步:程序启动后走while循环 #第七步:运行完accept函数后到这里
  29. #所有操作围绕一个对象self.sel实例变量核心对象展开的
  30. events = self.sel.select() #第二步:调用self.sel实例变量,监听的内容server封装到events对象里 #第八步:如果客户端发过来此刻监听的内容就有变化有俩个对象server和conn封装到events对象里
  31. for key, mask in events: #第三步:for循环events(可迭代对象)拿到key和mask #第九步:for循环events(可迭代对象)拿到key和mask
  32. callback = key.data #第四步:当前key.data是self.accept函数赋值给callback #第十步:当前key.data是read函数赋值给callback
  33. #key.fileobj是拿到的监听的对象。
  34. callback(key.fileobj, mask) #第五步:运行callback执行accpt()函数 #第十一步:运行callback执行read()函数里面放到的之前链接相应的文件描述符conn
  35. #print('当前监听的对象:', key.fileobj)
  36.  
  37. #第六步:accept函数接收连接服务端的客户端信息
  38. def accept(self,sock,mask): #接收sock和mask
  39. conn, addr = sock.accept() #sock.accept接收此时链接服务端的socket对象拿到conn和addr
  40. #print('accepted', conn, 'from', addr)
  41. print("from %s %s connected" %addr)
  42. conn.setblocking(False) #设置成非阻塞
  43. self.sel.register(conn, selectors.EVENT_READ, self.read) #把conn跟read做绑定后程序返回到handle()函数里的events继续监听
  44. #print(conn)
  45.  
  46. self.dic[conn] = {} #在空字典里进行了conn赋值,self.dic={conn:{},}
  47.  
  48. #第十二步:read函数返回给客户端ok
  49. def read(self,conn, mask): #接收了conn和mask
  50. try: #加异常防止客户端突然断开
  51. if not self.dic[conn]: #判断self.dic[conn]里面是否是空字典,如果是空字典,代表第一次进来
  52. data = conn.recv(1024) #conn接收了客户端发来的数据
  53. cmd,filename,filesize = str(data,encoding='utf-8').split('|') #把接收到客户端发来的包解开拿到cmd,filename,filesize个信息
  54. self.dic={conn:{"cmd" : cmd, "filename" : filename, "filesize" : int(filesize)}} #把拿到的cmd,filename,filesize信息放到self.dic字典里去后程序返回到handle()函数里的events继续监听
  55.  
  56. if cmd == 'put': #如果接收的信息是put
  57. conn.send(bytes("OK",encoding='utf8')) #给客户端返回一条数据
  58.  
  59. if self.dic[conn]['cmd'] == 'get':
  60. file = os.path.join(BASE_DIR,"upload",filename)
  61.  
  62. if os.path.exists(file):
  63. fileSize = os.path.getsize(file)
  64. send_info = '%s|%s' %('YES',fileSize)
  65. conn.send(bytes(send_info, encoding='utf8'))
  66. else:
  67. send_info = '%s|%s' %('NO',0)
  68. conn.send(bytes(send_info, encoding='utf8'))
  69.  
  70. else: #如果不是空字典代表不是第一次进来
  71. if self.dic[conn].get('cmd',None): #对接收的命令进行分发判断是put还是get
  72. cmd=self.dic[conn].get('cmd')
  73. if hasattr(self, cmd): #如果cmd=put调用put函数,如果是cmd=get函数调用get函数
  74. func = getattr(self,cmd)
  75. func(conn)
  76. else:
  77. print("error cmd!")
  78. conn.close()
  79. else:
  80. print("error cmd!")
  81. conn.close()
  82.  
  83. except Exception as e:
  84. print('断开的客户端信息是:', conn)
  85. self.sel.unregister(conn) #如果没有接收到数据做一个关闭解除
  86. conn.close()
  87.  
  88. #put上传函数
  89. def put(self, conn):
  90. fileName = self.dic[conn]['filename']
  91. fileSize = self.dic[conn]['filesize']
  92. path = os.path.join(BASE_DIR,"upload",fileName) #拿到要接收的信息
  93. #print(fileName,fileSize,path)
  94. recv_data = conn.recv(1024) #接收客户端上传的数据1024字节
  95. self.hasReceived += len(recv_data) #把接收的数据累加到变量self.hasReceived
  96.  
  97. with open(path, 'ab') as f: #打开文件
  98. f.write(recv_data) #把接收的数据写到文件里去
  99.  
  100. if fileSize == self.hasReceived: #判断文件大小跟接收大小是否一样
  101. if conn in self.dic.keys(): #如果文件大小跟接收大小一样清空字典
  102. self.dic[conn] = {}
  103. print("%s 上传完毕!" %fileName)
  104.  
  105. if __name__=='__main__':
  106. selectFtpServer() #第一步:实例化触发selectFtpServer这个类

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

  1. import socket
  2. import os,sys
  3. BASE_DIR=os.path.dirname(os.path.abspath(__file__))
  4.  
  5. class selectFtpClient:
  6. def __init__(self):
  7. self.args=sys.argv #sys.argv在命令行输入的参数,第一个参数默认文件名,第二个参数跟IP地址和端口
  8. if len(self.args)>1: #如果大于1把第二个参数俩个值赋值给port
  9. self.port=(self.args[1],int(self.args[2]))
  10. else:
  11. self.port=("192.168.1.160",8080) #如果没有第二个参数默认取这个
  12. self.create_socket() #
  13. self.command_fanout() #进行命令分发
  14.  
  15. #create_socket函数创建socket对象连接服务端
  16. def create_socket(self):
  17. try:
  18. self.sk = socket.socket()
  19. self.sk.connect(self.port)
  20. print('连接FTP服务器成功!')
  21. except Exception as e:
  22. print("eroor:",e)
  23.  
  24. #command_fanout()函数进行命令分发
  25. def command_fanout(self):
  26. while True:
  27. cmd = input('>>>').strip() #引导用户输入上传还是下载
  28. if cmd == 'exit()':
  29. break
  30. cmd,file = cmd.split() #把输入的命令分开进行反射
  31. if hasattr(self,cmd):
  32. func = getattr(self,cmd)
  33. func(cmd,file)
  34. else:
  35. print('调用错误!')
  36.  
  37. #put()上传函数
  38. def put(self,cmd,file):
  39.  
  40. if os.path.isfile(file): #判断本地文件是否存在
  41. fileName = os.path.basename(file) #取出文件的名字
  42. fileSize = os.path.getsize(file) #取出文件的大小
  43. fileInfo = '%s|%s|%s'%(cmd,fileName,fileSize) #给文件名字大小打包成fileInf
  44. self.sk.send(bytes(fileInfo, encoding='utf8')) #调用send方法把fileInf发给服务端
  45. recvStatus = self.sk.recv(1024) #接收服务端返回的OK内容
  46. print('recvStatus' , recvStatus)
  47. hasSend = 0
  48. if str(recvStatus, encoding='utf8') == "OK": #如果接收到服务端返回的OK
  49. with open(file, 'rb') as f: #打开文件
  50. while fileSize > hasSend : #循环的去上传文件
  51. contant = f.read(1024)
  52. recv_size = len(contant)
  53. self.sk.send(contant)
  54. hasSend += recv_size
  55. s=str(int(hasSend/fileSize*100))+"%"
  56. print("正在上传文件: "+fileName+" 已经上传:" +s)
  57. print('%s文件上传完毕' % (fileName,))
  58. else:
  59. print('文件不存在')
  60.  
  61. #get()下载函数
  62. def get(self,cmd,file):
  63. pass
  64.  
  65. if __name__=='__main__':
  66. 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. 清除冗余的css

    下载旧版的火狐浏览器,如Firefox 48.0.exe, 下载地址:https://ftp.mozilla.org/pub/firefox/releases/48.0/win32/zh-CN 关闭更 ...

  2. 五、Vi和Vim编辑器

    1. Vim编辑器: 在Linux下一般使用vi编辑器来编辑文件.vi既可以查看文件也可以编辑文件.三种模式: 命令行.插入.底行模式 切换到命令行模式:按Esc键: 切换到插入模式:按 i .o.a ...

  3. bluemix创建docker容器

    简介: bluemix是基于kubernetes来服务的免费云空间.绑定信用卡后可以创建一个月的集群,一个月后会被删除. 下面示例介绍如何使用kubernetes dashboard来创建一个容器,并 ...

  4. Vue 插槽

    插槽的概念: 插槽的关键字slot,默认情况下,组件中的模板会覆盖组件中的原始内容(即自定义标签对内部的内容会不显示),解决办法就是使用插槽. 组件的原始内容: 即在vue实例范围之内,因此可以调用实 ...

  5. Ubuntu 17.04版本下,opencv进行源码编译安装

    本文主要针对Ubuntu 17.04版本下,opencv进行源码编译安装.开发环境主要针对python 对 openCV库的调用. 安装 gcc cmake 编译环境 sudo apt-get ins ...

  6. mpeg4文件分析(纯c解析代码)

    参考链接: 1. MPEG4码流的帧率计算 https://blog.csdn.net/littlebee90/article/details/68924690                2. M ...

  7. Git设置旧邮箱与现邮箱不一致问题

    设置名字和邮箱git config user.name 'lhr' git config user.email 'lhr@qq.com' 工程根目录创建email.sh文件粘贴以下代码 #!/bin/ ...

  8. 使用U盘为龙芯笔记本安装操作系统

    摘要:在没有光驱的情况下,可以使用dd命令或者ultraISO软件制作Linux安装U盘,方法适合龙芯和X86.AMD64的设备. 前段时间,由于开发需要,拿到了一部龙芯3A3000的笔记本.出厂的安 ...

  9. Python字典的一点用法

    #python的基本语法网上已经有很多详细的解释了,写在这里方便自己记忆一些 字典是一种映射类型的数据结构,(映射一般是数学中的术语,指两个元素之间元素相互对应的关系).字典和序列有很大的不同,序列类 ...

  10. 【SoftwareTesting】Homework2

    For the Program1, For Question1: The fault is that in the loop condition, ' i ' should be not less t ...