python selectors模块实现 IO多路复用机制的上传下载,python模块有哪些
import selectors
import socket
import os,time
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
class Server:
# sel = selectors.DefaultSelector()
def __init__(self):
self.ip_port=('127.0.0.1',8080)
self.sel=selectors.DefaultSelector()
#根据平台选择最佳的IO多路机制,比如linux就会选择epoll
self.dic = {}
self.create_sock()
self.handle()
def create_sock(self):
sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
# sock.setblocking(False)
#注册监听对象,绑定accept
self.sel.register(sock, selectors.EVENT_READ, self.accept
def handle(self):
while True:
#sel监听sock变化,当sock实例化时,赋值给events,通过回调函数触发
#key.data(key.fileobj,mask) accept(sock,mask),
#当有客户端连接时通过accept注册到read……
events = self.sel.select() # [sock,conn1,conn2]
for key, mask in events:
callback = key.data # sel accept sel read
callback(key.fileobj, mask) #accept(sock,mask),read(conn1,mask)……
def accept(self,sock, mask):
print('登录服务端---')
conn, addr = sock.accept() # Should be ready
print('accepted', conn, 'from', 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)
try:
cmd, filename, filesize = str(data.decode("utf-8")).split("|")
self.dic[conn] = {"cmd": cmd, "filename": filename, "filesize": filesize, "hasReceived": 0}
except Exception as e:
cmd, filename = str(data.decode("utf-8")).split("|")
self.dic[conn] = {"cmd": cmd, "filename": filename,"filesize": os.path.getsize(os.path.join(BASE_DIR, "load", filename)),"hasSended": 0}
if cmd=='put':#上传
conn.send('ok'.encode('utf8'))
if cmd=='get':#下载
conn.send(str(self.dic[conn]['filesize']).encode('utf8'))
else:
if self.dic[conn].get('cmd',None):
cmd =self.dic[conn].get('cmd')
if hasattr(self,cmd):
func=getattr(self,cmd)
func(conn,mask)#反射命令分发
else:
print('error')
except Exception as e:
print(e,conn,'断开连接')
conn.close()
self.sel.unregister(conn)
def put(self,conn,mask):
filename=self.dic[conn]['filename']
filesize = self.dic[conn]['filesize']
path = os.path.join(BASE_DIR, "upload", filename)
data = conn.recv(1024)
conn.send("success".encode("utf-8"))
self.dic[conn]['hasReceived'] += len(data)
with open(path, "ab") as f:
f.write(data)
if self.dic[conn]['hasReceived'] == self.dic[conn]['filesize']:
self.dic[conn] = {}
print("上传结束")
#少写一步
def get(self, conn, mask):
filename = self.dic[conn]['filename']
path = os.path.join(BASE_DIR, "load", filename)
with open(path, "rb") as f:
f.seek(self.dic[conn]["hasSended"], 0)
data = f.read(1024)
conn.send(data)
self.dic[conn]['hasSended'] += len(data)
if self.dic[conn]['hasSended'] == self.dic[conn]["filesize"]:
self.dic[conn] = {}
print("下载结束")
time.sleep(0.5)
if __name__ == "__main__":
Server()
import os, time, sys
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
import socket
import selectors
class selectFtpClient:
def __init__(self):
self.port = ("127.0.0.1", 8001)
self.create_socket()
self.command_fanout()
def create_socket(self):
try:
self.sock = socket.socket()
self.sock.connect(self.port)
print("连接FTP成功!")
except Exception:
print("连接失败!")
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.sock.send(bytes(fileInfo, encoding="utf-8"))
recvStatus = self.sock.recv(1024)
hasSend = 0
if str(recvStatus, encoding="utf-8") == 'ok':
with open(file, "rb") as f:
while fileSize > hasSend:
contant = f.read(10)
recv_size = len(contant)
self.sock.send(contant)
hasSend += recv_size
s = str(int(hasSend / fileSize * 100)) + "%"
print("正在上传文件:" + fileName + " 已经上传: " + s)
time.sleep(0.5)
print("%s文件上传完毕" % (fileName,))
else:
print("文件不存在")
# 下载
def get(self, cmd, file):
fileInfo = "%s|%s" % (cmd, file)
self.sock.send(bytes(fileInfo, encoding="utf-8"))
filesize = int(self.sock.recv(10).decode("utf-8"))
f = open(file, "ab")
i = 0
while i < filesize:
self.sock.send("ok".encode("utf-8"))
data = self.sock.recv(10)
f.write(data)
i += len(data)
s = str(int(i / filesize * 100)) + "%"
print("正在上传文件:" + file + " 已经下载: " + s)
print("下载完成")
f.close()
if __name__ == "__main__":
selectFtpClient()
评论关闭