#!/usr/bin/env python
#-*-coding:utf-8-*-
#ftp客户端
import os
import socket
import threading
import socketserver
#下载文件
def get_file(host,port,filepath):
s=socket.socket()
s.connect((host,port))
filepath=os.path.join('.','bakc','filepath')
f=open(filepath,'wb')
data=True
while data:
data=s.recv(1024)
if data:
f.write(data)
s.close()
f.close()
#上传文件
def put_file(host,port,filepath):
s=socket.socket()
s.connect((host,port))
f=open(filepath,'rb')
while True:
data=f.read(1024)
if data:
s.sendall(data)
else:
break
s.close()
f.close()
class FtpClient:
def __init__(self,host='localhost',port=21):
self.host=host
self.port=port
self.cmds=('QUIT','USER','NOOP','TYPE','PASV','PORT','RETR','STOR')
self.linesep='\n'
self.data_port=None
self.loged=False
self.sock=None
self.pasv_mode=None
self.pasv_host=None
self.pasv_port=None
def cmd_connect(self):
self.sock=socket.socket()
self.sock.connect((self.host,self.port))
self.data_port=self.sock.getsockname()[0]
def start(self):
print('支持的命令: ',self.cmds)
self.cmd_connect()
self.login()
while True:
cmd=input('请输入FTP命令: ')
if not cmd:
print('FTP命令不能为空')
continue
cmd,args=self.split_args(cmd)
if not self.send_cmd(cmd,args):
continue
res=self.readline(self.sock)
print(res)
if cmd.startswith('PASV') and res.startswith('227'):
self.pasv_mode=True
servinfo=res[res.index('(')+1:res.index(')')]
self.pasv_host='.'.join(servinfo.split(',')[:4])
servinfo=servinfo.split(',')[-2:]
self.pasv_port=256*int(servinfo[0])+int(servinfo[1])
if cmd.startswith('RETR'):
if self.pasv_mode:
threading.Thread(target=get_file,args=(self.pasv_host,self.pasv_port,args)).start()
if cmd.startswitch('STOR'):
if self.pasv_mode:
threading.Thread(target=put_file,args=(self.pasv_host,self.pasv_port,args)).start()
if cmd.startswitch('QUIT'):
break
self.sock.close()
self.sock=None
def login(self):
if self.sock:
self.send_cmd('USER')
res=self.readline(self.sock)
if res.startswitch('230'):
print('登录成功!')
self.loged=True
def readline(self,sock):
data=''
while not data.endswith(self.linesep):
d=sock.recv(1)
data+=d.decode('utf-8')
return data
def split_args(self,cmds):
if ' ' in cmds:
cmdlsts=cmds.split(' ')
cmd=cmdlsts[0]
args=' '.join(cmdlists[1:])
else:
cmd=cmds
args=''
return cmd.upper(),args
def send_cmd(self,cmd,args=''):
if self.sock:
if args:
cmd=' '.join((cmd,args))
if cmd.startswith('RETR') or cmd.startswith('STOR'):
if self.pasv_mode is None:
print('Please appoint port or stor mode.')
return False
if not args:
return False
if cmd.startswith('STOR'):
if args:
if not os.path.exists(args):
print('File is not exists')
return False
cmd+=self.lineseps
self.sock.sendall(cmd.encode('utf-8'))
return True
if __name__=='__main__':
fc=FtpClient()
fc.start()
#!/usr/bin/env python
#-*-coding:utf-8-*-
#ftp服务器的定义
import socket
import socketserver
import time
import threading
import os
class FTPHdl(socketserver.StreamRequestHandler):
def __init__(self,request=None,client_address=None,server=None):
#实例属性,所有命令
self.coms_keys=('QUIT','USER','NOOP','TYPE','PASV','PORT','RETR','STOR')
#命令与方法映射
self.coms={}
self.init_coms()
self.server=server
#命令端口
self.cmd_port=21
#数据端口
self.data_port=20
self.pasv_data_ip=None
self.pasv_data_port=None
#参数
self.args=None
#是否登入
self.loged=False
#主动模式,被动模式
self.pasv_mode=None
super().__init__(request,client_address,server)
#初始话所有命令
def init_coms(self):
for k in self.coms_keys:
self.coms[k]=getattr(self,'exe_'+k.lower())
#客户端处理
def handle(self):
while True:
#获得命令
cmds=self.rfile.readline()
if not cmds:
continue
cmds=cmds.decode('utf-8')
#命令分析
cmd=self.deal_args(cmds)
#命令动词
if cmd in self.coms_keys:
self.coms.get(cmd)()
#不在定义的命令之内
else:
self.send(500,'Invaild command.')
if cmd=='QUIT':
break
#处理命令行
def deal_args(self,cmds):
#命令动词,命令参数分割
if ' ' in cmds:
cmd,args=cmds.aplit(' ')
args=args.strip('\n').strip()
#只有命令动词
else:
cmd=cmds.strip('\n')
args=''
#参数为空
if args:
self.args=args
#返回命令动词
return cmd.upper()
#用户退出
def exe_quit(self):
self.send(221,'bye')
#用户登入
def exe_user(self):
user=self.args
#用户名为空或默认
if user in ('','anonymous'):
user='anonymous'
self.loged=True
#登入已经
self.send(230,'identified!')
#没有登入,匿名
else:
self.send(530,'Only use anonymous')
#被动模式
def exe_pasv(self):
if not self.loged:
#要求登入
self.send(332,'Please login.')
return
#已经进入被动模式
if self.pasv_mode:
#发送用户信息。IP端口号发送客户端
info='entering passive mode (%s)' % self.make_pasv_info()
self.send(227,info)
return
try:
#进入被动模式
self.enter_pasv()
info='entering passive mode (%s)' % self.make_pasv_info()
self.pasv_mode=True
self.send(227,info)
except Exception as e:
print(e)
self.send(500,'Failure change to passive mode.')
#被动模式下数据连接服务器的地址和端口
def make_pasv_info(self):
ip_info=self.pasv_data_ip.split('.')
ip_info=','.join(ip_info)
porta=str(self.pasv_data_port // 256)
portb=str(self.pasv_data_port % 256)
return ','.join((ip_info,porta,portb))
#进入被动模式
def enter_pasv(self):
if self.server.data_server is None:
self.pasv_data_ip,self.pasv_data_port=self.server.create_data_server()
#进入主动模式
def exe_port(self):
self.send(500,'Do not offer port mode.')
def exe_noop(self):
self.send(200,'ok')
def exe_type(self):
self.send(200,'ok')
#下载文件
def exe_retr(self):
if not os.path.exists(self.args):
self.send(550,'File is not exists.')
return
client_addr=self.request.getpeername()[0]
#获得ip地址
self.add_opr_file(client_addr,('RETR',self.args))
self.send(150,'ok.')
#上传文件
def exe_stor(self):
client_addr=self.request.getpeername()[0]
self.add_opr_file(client_addr,('STOR',self.args))
self.send(150,'ok.')
def add_opr_file(self,client_addr,item):
if client_addr in DataHdl.client_opr:
DataHdl.client_opr[client_addr].append(item)
else:
DataHdl.client_opr[client_addr]=[item,]
def send(self,code,info):
infos='%d %s\n' % (code,info)
self.request.sendall(infos.encode('utf-8'))
class MyThrTCPServ(socketserver.ThreadingTCPServer):
def __init__(self,addr,Hdl):
self.data_server=None
super().__init__(addr,Hdl)
def shutdown(self):
if self.data_server:
threading.Thread(target=self.data_server.shutdown).start()
super().shutdown()
def create_data_server(self):
self.data_server=socketserver.ThreadingTCPServer(('127.0.0.1',0),DataHdl)
pasv_data_ip,pasv_data_port=self.data_server.server_address
threading.Thread(target=self.data_server.serve_forever).start()
return pasv_data_ip,pasv_data_port
class DataHdl(socketserver.StreamRequestHandler):
client_opr={}
def handle(self):
peerip=self.request.getpeername()[0]
opr=self.get_opr_args(peerip)
if opr:
if opr[0]=='RETR':#下载文件
self.retr_file(opr[1])
elif opr[0]=='STOR':#上传文件
self.stor_file(opr[1])
def get_opr_args(self,peerip):
if peerip in self.client_opr:
opr=self.client_opr[peerip]
if not self.client_opr[peerip]:
self.client_opr.pop(peerip)
return opr
#发送文件
def retr_file(self,filepath):
f=open(filepath,'rb')
while True:
data=f.read(1024)
if data:
self.request.sendall(data)
else:
break
f.close()
#接受文件
def stor_file(self,filepath):
f=open(os.path.join('.','bakt',filepath),'wb')
while True:
data=self.request.recv(1024)
if data:
f.write(data)
else:
break
f.close()
if __name__=='__main__':
server=MyThrTCPServ(('127.0.0.1',21),FTPHdl)
threading.Thread(target=server.serve_forever).start()
print('FTP start...')
time.sleep(30)
server.shutdown()
socket网络编程ftp
最新推荐文章于 2023-07-04 14:53:19 发布