###服务端
import os
import socket
import time
import selectors
print(os.path.abspath(__file__))#打印当前文件路径
print(os.path.dirname(os.path.abspath(__file__)))#获取当前文件路径的上一级目录路径
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
class selectFtpServer:
def __init__(self):
self.dic = {}
self.hasReceived = 0
self.sel = selectors.DefaultSelector()#给一个默认的IO多路复用方式
self.create_socket()
self.handler()
def create_socket(self):
sock = socket.socket()
sock.bind(('127.0.0.1',8090))
sock.listen(5)
self.sel.register(sock,selectors.EVENT_READ,self.accept)#把sock和accept绑定
print('服务端已开启,等待用户连接。。。')
def handler(self):
while True:
event = self.sel.select()#这里面是个列表,存放点sock,conn等信息
for key,mast in event:
call_back = key.data#这是一个函数,accept函数,后面的accept函数和read函数是固定用法,不写这个地儿是过不去的
call_back(key.fileobj,mast)#key.fileobj在没有链接进来时是sock,再有链接进来时存的是conn
def accept(self,sock,mast):
conn,addr = sock.accept()
self.sel.register(conn,selectors.EVENT_READ,self.read)#把conn和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":filesize
}
print(self.dic)
if cmd == 'put':
conn.send(bytes('OK',encoding='utf8'))
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='utf8'))
else:
send_info = '%s|%s'%('No',0)
conn.send(bytes(send_info, encoding='utf8'))
else:
if self.dic[conn].get('cmd',None):#get('cmd',None)意思是conn这个字典里如果存在‘cmd’这个键,
# 那么取出来,如果不存在则返回一个None
print(self.dic[conn].get('cmd'))
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')
except Exception as e:
print('error',e)
self.sel.unregister(conn)
conn.close()
def put(self,conn):
self.hasReceived = 0
fileName = self.dic[conn]['filename']
fileSize = self.dic[conn]['filesize']
path = os.path.join(BASE_DIR,'upload',fileName)#创建文件路径
print(path)
while self.hasReceived < int(fileSize):
recv_data = conn.recv(1024)
self.hasReceived += len(recv_data)
with open(path,'wb') as f:
f.write(recv_data)
if int(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__':
ftp = selectFtpServer()
###客户端
import socket
import time
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
class selectFtpClient:
def __init__(self):
self.createSocket()
self.command_out()
def createSocket(self):
try:
self.client = socket.sockput
self.client.connect(('127.0.0.1',8090))
print('链接FTP服务器成功')
except Exception as e:
print('error:',e)
def command_out(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 get(self,cmd,file):
pass
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)
print(fileInfo)
self.client.send(bytes(fileInfo,encoding='utf8'))
recvStatus = self.client.recv(1024)
print('recvStatus:',recvStatus)
hasSend = 0
print(file)
if str(recvStatus,encoding='utf8')== 'OK':
with open(file,'rb') as f:
while fileSize>hasSend:
contant = f.read(1024)
recv_size = len(contant)
self.client.send(contant)
hasSend += recv_size
s = str(int(hasSend/fileSize*100)) + '%'
print('正在上传文件:'+fileName+'已经上传:'+s)
print('%s文件上传完毕'%fileName)
else:
print('文件不存在')
if __name__ == '__main__':
c = selectFtpClient()