import socket
import os,sys
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) class selectFtpClient:
def __init__(self):
self.args = sys.argv
if len(self.args)>1:
self.port = (self.args[1],int(self.args[2]))
else:
self.port = ('10.30.40.61',8080)
self.create_socket()
self.command_fanout()
def create_socket(self):
try:
self.sk = socket.socket()
self.sk.connect(self.port)
print('连接服务器成功!')
except Exception as e:
print('error:',e)
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('调用错误')
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)
self.sk.send(bytes(fileInfo,encoding='utf-8'))
recvStatus = self.sk.recv(1024)
print('recvStatus',recvStatus)
hasSend = 0
if str(recvStatus,encoding='utf-8') == '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('文件不存在')
def get(self,cmd,file):
pass
if __name__ == '__main__':
selectFtpClient()
###################################################################################################
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
#os.path.dirname(os.path.abspath(__file__)):当前文件的绝对路径,适用于各种python的架构全局变量
import time
import socket
import selectors
'''
思路:
'''
class selectFtpServer:
def __init__(self):
self.dic = {}
self.hasReceived = 0
self.sel = selectors.DefaultSelector()
self.create_socket()
self.handle()
def create_socket(self):
server = socket.socket()
server.bind(('10.30.40.61',8080))
server.listen(5)
server.setblocking(False)
self.sel.register(server,selectors.EVENT_READ,self.accept)
print('服务端已开启,等待用户连接....')
def handle(self):
while True:
events = self.sel.select()
for key,mask in events:
callback = key.data
callback(key.fileobj,mask)
def accept(self,sock,mask):
conn,addr = sock.accept()
print('from %s %s connected'%addr)
conn.setblocking(False)
self.sel.register(conn,selectors.EVENT_READ,self.read) self.dic[conn] = {}
def read(self,conn,mask):
try:
if not self.dic[conn]:
data = conn.recv(1024)
cmd,filename,filesize = str(data,encoding='utf-8').split('|')
self.dic = {conn:{'cmd':cmd,'filename':filename,'filesize':int(filesize)}} if cmd == 'put':
conn.send(bytes('OK',encoding='utf-8')) if self.dic[conn]['cmd'] =='get':
file = os.path.join(BASE_DIR,'download',filename) if os.path.exists(file):
fileSize = os.path.getsize(file)
send_info = '%s|%s'%('YES',fileSize)
conn.send(bytes(send_info,encoding='utf-8'))
else:
send_info = '%s|%s'%('NO',0)
conn.send(bytes(send_info,encoding='utf-8'))
else:
if self.dic[conn].get('cmd',None):
cmd = self.dic[conn].get('cmd')
if hasattr(self,cmd):
func = getattr(self,cmd)
func(conn)
else:
print('error cmd!')
conn.close()
else:
print('error cmd!')
conn.close()
except Exception as e:
print('error',e)
self.sel.unregister(conn)
conn.close()
def put(self,conn):
fileName = self.dic[conn]['filename']
fileSize = self.dic[conn]['filesize']
path = os.path.join(BASE_DIR,'upload',fileName)
recv_data = conn.recv(1024)
self.hasReceived +=len(recv_data) 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)
def get(self,conn): filename = self.dic[conn]['filename']
path = os.path.join(BASE_DIR,'download',filename)
if str(conn.recv(1024),'utf-8') == 'second_active':
with open(path,'rb') as f:
for line in f:
conn.send(line)
self.dic[conn] = {}
print('文件下载完毕!')
if __name__ == '__main__':
selectFtpServer()

基于selectors模块实现并发的FTP的更多相关文章

  1. SELECTORS模块实现并发简单版FTP

    环境:windows, python 3.5功能:使用SELECTORS模块实现并发简单版FTP允许多用户并发上传下载文件 结构:ftp_client ---| bin ---| start_clie ...

  2. python 并发编程 基于gevent模块实现并发的套接字通信

    之前线程池是通过操作系统切换线程,现在是程序自己控制,比操作系统切换效率要高 服务端 from gevent import monkey;monkey.patch_all() import geven ...

  3. 基于socketserver模块实现并发的套接字(tcp、udp)

    tcp服务端:import socketserver class MyHandler(socketserver.BaseRequestHandler): def handle(self): #通信循环 ...

  4. IO模型《七》selectors模块

    一 了解select,poll,epoll IO复用:为了解释这个名词,首先来理解下复用这个概念,复用也就是共用的意思,这样理解还是有些抽象, 为此,咱们来理解下复用在通信领域的使用,在通信领域中为了 ...

  5. day33 网络编程之线程,并发以及selectors模块io多路复用

    io多路复用 selectors模块 概要: 并发编程需要掌握的知识点: 开启进程/线程 生产者消费者模型!!! GIL全局解释器锁(进程与线程的区别和应用场景) 进程池线程池 IO模型(理论) 1 ...

  6. python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...

  7. (IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    参考博客: https://www.cnblogs.com/xiao987334176/p/9056511.html 内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yi ...

  8. 并发编程之IO模型比较和Selectors模块

    主要内容: 一.IO模型比较分析 二.selectors模块 1️⃣ IO模型比较分析 1.前情回顾: 上一小节中,我们已经分别介绍过了IO模型的四个模块,那么我想大多数都会和我一样好奇, 阻塞IO和 ...

  9. Python selectors实现socket并发

    selectors模块 此模块允许基于选择模块原语构建高级别和高效的I / O多路复用. 鼓励用户使用此模块,除非他们想要精确控制使用的os级别的原语. 注:selectors也是包装了select高 ...

随机推荐

  1. C++ STL - queue使用详解

    c++队列模板类的定义在<queue>头文件中,queue 模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型. 下面详细介绍 ...

  2. [模板]Matrix Tree定理

    结论:一个图的生成树个数等于它的度数矩阵减邻接矩阵得到的矩阵(基尔霍夫矩阵)的任意一个n-1阶主子式的行列式的绝对值 证明:不会 求法:高斯消元 例题:[HEOI2013]小Z的房间 #include ...

  3. tomcat work目录的作用就是编译每个项目里的jsp文件为java文件如果项目没有jsp页面则这个项目文件夹为空

    最近发现,很多网友喜欢把tomcat的work目录里的东西叫做缓存,其实那不是很恰当,work目录只是tomcat的工作目录,也就是tomcat把jsp转换为class文件的工作目录,这也正是为什么它 ...

  4. ExtJs--16--Ext.override()方法专门用来重写对象的方法

    Ext.onReady(function(){ /** * Ext.override()方法专门用来重写对象的方法 */ //定义个类 Ext.define("U",{ //该类的 ...

  5. Cocos Code IDE

    https://www.cnblogs.com/luorende/p/6464181.html http://www.cocoachina.com/bbs/read.php?tid-464164.ht ...

  6. Oracle回滚段的概念,用法和规划及问题的解决

    回滚段概述  回滚段用于存放数据修改之前的值(包括数据修改之前的位置和值).回滚段的头部包含正在使用的该回滚段事务的信息.一个事务只能使用一个回滚段来存放它的回滚信息,而一个回滚段可以存放多个事务的回 ...

  7. 2.linux系统命令详解

    1 shell shell:命令解释器,根据输入的命令执行相应命令. 1.1 shell家族 察看当前系统下有哪些shell: cat /etc/shells 察看当前系统正在使用的shell ech ...

  8. OC中的类扩展

    类扩展 是在原有类的基础扩展一个新的属性和对象方法 但是方法的实现还是要写在原有的声明中,不然是不会被访问到的 类扩展可以扩展在新的头文件中,然后在主函数中导入. 利用类扩展可以变相的实现属性的私有化 ...

  9. POJ 1414 暴搜

    题意比较复杂 (但是很好理解) 大概意思是给你等边三角形(详见题目中的图). 最后一行有n个数,下一次要填的数是c. 里面预先已经填好了数字.(0为未填) 得分的标准是这个分数的连通块周围没有空的地方 ...

  10. 基于Redis实现分布式应用限流--转

    原文地址:https://my.oschina.net/giegie/blog/1525931 摘要: 限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限 ...