pythonsocket自动化教程_Python自动化开发从浅入深-进阶(socketServer)

#!/usr/bin/env python#__author__:ZhaoHong#-*- coding: utf-8 -*-

importsocketserverimporttime,os,sys,re,hashlibfrom subprocess importPIPE,Popenfrom multiSocketFTP.multiFTPServer.set importsetting

_FILE_SLIM= (100*1024*1024) #100MB

classFTPServerHandle(socketserver.BaseRequestHandler):'''It's a class for handle FTPServer.

socketserver is a multthreading base class,'''

defhandle(self):whileTrue:########## -------------------------------------------------------------------------------------------------beginning recive

self.data = self.receiveFromClient(1024) #----------------------------------------------------------------receive

print ("from client : [{}] \nthe server has got data is : [{}]"\

.format(self.client_address[0],self.data))#print gotted message

########## -------------------------------------------------------------------------------------------------have not data

if not self.data:#if data is not sented,we will break loop.

print ("client {} stop to send data.".format(self.client_address[0]))break

########## -------------------------------------------------------------------------------------------------receive data handle here

## cmdHead : judge "handle branch"

##################################

#we will handle the data of recieve,follow the agreement below:

user_input = self.data.split() #use split fuction to make a list for data

cmdHead = user_input[0] #get head about input command from client

if cmdHead == 'welcome': #if head is welcome then show welcome message. it's show at begining

print("welcome to use FTP SERVER...")

self.sendToClient('Welcome to use FTP\n=================') ## ------------------------------------welcome 1

#self.request.sendall(bytes('Welcome to use FTP\n=================','utf-8'))

if cmdHead == 'welcome_show_ok':continue

#---------------------------------------------------------------------------------------------------------- login --

#fisrt we must handle login process,otherwish we dont handle other command from client.

#(user_input list length must be 3)

elif cmdHead == 'login' and len(user_input) == 3:

cmdUserName= user_input[1] #get user name from client

cmdUserPassword = user_input[2] #get user password from client

#****** admin login begin *********

(isLogin,username,directory,quota) = self.userlogin(cmdUserName,cmdUserPassword,setting.userInfo)##----- Login Infomation---

if isLogin:##------------------------------------------------------------------------------------------ enter Login ###

print("{}:login FTP success!".format(cmdUserName))

self.sendToClient('loginSuccess')##-------------------------------------------------------------- login sucess 2

if setting.sysStr == 'Windows':

os.chdir("%s\\%s"%(setting.homeDIR,cmdUserName)) #cd to acount home drectory(windows)

os.system("cd")else:

os.chdir("%s/%s"%(setting.homeDIR,cmdUserName)) #cd to acount home drectory(linux)

os.system("pwd")while True:#--------------------------------------------------------------------------------------{loop begin} FTP cmd handle

#命令格式:cd 目录

#get filename

#put filename

ret = self.receiveFromClient(1024) #------------------------------------------------------------wait [recv] 1

ftpInput = ret.split() #split string to list (separator is spaces)

if ret == '':continue

print("command:%s"%ret)if re.search(r"^cd",ret) and len(ftpInput) >= 2:#----------------------------------------------cd DIR

print(user_input[1])if setting.sysStr == "Windows":if ftpInput[1] == 'home':

Directory= "%s%s"%(setting.homeDIR,username)else:

Directory= "%s%s\\%s"%(setting.homeDIR,username,ftpInput[1])else:if ftpInput[1] == 'home':

Directory= "%s%s"%(setting.homeDIR,username)else:

Directory= "%s%s/%s"%(setting.homeDIR,username,ftpInput[1])#cmd = "cd %s"%Directory

try:

os.chdir(Directory)

self.sendToClient(Directory)except:

self.sendToClient("directory is not found")print("directory is not found")#-----------------------------------------------------------------------------------------------ls,dir

elif (re.search(r"^ls",ret) and len(ftpInput) >= 1) or\

re.search(r"^dir",ret) :

retDIR=os.popen(ret).read()

self.sendToClient(retDIR)#if setting.sysStr == "Windows":

#self.sendToClient(bytes(retDIR,'gbk'))

#else:

#self.sendToClient(bytes(retDIR,'gbk'))

#------------------------------------------------------------------------------------------------get srcFilename drcFilename srcDIR drcDIR

elif re.search(r"^get",ret):#开始 get

print ("starting to get file ...")if setting.sysStr == "Windows":#获取文件名

pathFile = "%s%s\\%s"%(setting.homeDIR,ftpInput[3],ftpInput[1])

saveSizeFile= "%s%s\\%s"%(setting.homeDIR,ftpInput[3],"srcFileSize.dat")

saveBreakFile= "%s%s\\%s"%(setting.homeDIR,ftpInput[3],"breakAt.dat")else:

pathFile= "%s%s/%s"%(setting.homeDIR,ftpInput[3],ftpInput[1])#ftpInput[1]: path,ftpInput[2]:src filename ftpInput[2]: drc filename

saveSizeFile = "%s%s\\%s"%(setting.homeDIR,ftpInput[3],"srcFileSize.dat")

saveBreakFile= "%s%s\\%s"%(setting.homeDIR,ftpInput[3],"breakAt.dat")

self.request.sendall(b"get")#---------------------------------------------------------------send get

msg = self.request.recv(500) #---------------------------------------------------------------recv (获取文件客户端是否已经下载这个文件)

msg = str(msg,'utf-8')

msg1= msg.split('|')if msg1[0] == 'notHaveFile':#如果没有下载,就从头开始下载

md5Value = self.file_md5(pathFile)#获取源文件的MD5值

fileSize = self.writeFileSize(pathFile,saveSizeFile)#获取源文件的总计数

self.getFile(pathFile,saveBreakFile,fileSize,md5Value) #----------------------------------------------------------function getfile

elif msg1[0] == 'MD5':#否则,开始断点续传

fromClientFileMD5 = msg1[1]#获取客户端的MD5值

md5Value = self.file_md5(pathFile)#获取源文件的MD5值

fileSize= self.writeFileSize(pathFile,saveSizeFile)#获取源文件的总计数

if md5Value == fromClientFileMD5:#对比服务端源文件和客户端目标文件的MD5值,相等

print("文件已经成功下载")

self.request.sendall(b'fileIsdownload')#------------------------------------------send 文件已经下载 fileIsdownload

else:#否则,进入断点续传

breakat = self.getBreakAT(pathFile)#获取断点位置数字

self.getBreakFile(pathFile,saveBreakFile,breakat,fileSize,md5Value)#-----------------进入断点续传 function

#-----------------------------------------------------------------------------------------------put srcFilename drcFilename srcDIR drcDIR

elif re.search(r"^put",ret):if setting.sysStr == "Windows":

fileName= "{}{}\\{}".format(setting.homeDIR,ftpInput[4],ftpInput[2])else:

fileName= "{}{}/{}".format(setting.homeDIR,ftpInput[4],ftpInput[2])#fileName = "{}/{}".format(setting.homeDIR,head[1])

print(fileName)

t=os.path.isfile(fileName)ift:print(fileName)

fileMD5=self.file_md5(fileName)

s= "MD5|{}".format(fileMD5)

self.request.recv(200)#--------------------------------------------------------------------------------recv b'get'

self.request.sendall(bytes(s,'utf-8'))#---------------------------------------------------------------send MD5

lineSize =0

self.putFile(self.request,fileName)else:

self.request.recv(200)#--------------------------------------------------------------------------------recv b'get'---(1)

self.request.sendall(b'notHaveFile|a')#--------------------------------------------------------send (notHaveFile)

self.putFile(self.request,fileName)elif re.search(r"^quitFTP",ret):#--------------------------------------------------------------quit

self.request.sendall(b'OK')else:#------------------------------------------------------------------------------------------other handle

retForCmd = Popen(ret,shell=True,stdout=PIPE).stdout.read()#self.request.sendall(retForCmd)print(retForCmd)else:

self.sendToClient('')elif cmdHead == "ssh":

self.sshHandle()else:pass

defreceiveFromClient(self,length):

self.data= self.request.recv(length).strip()#waiting for receiv message,it's can get 1024 character one time

self.data = str(self.data,'utf-8')returnself.datadefsendToClient(self,str):

self.request.sendall(bytes(str,'utf-8'))defsshHandle(self):whileTrue:

self.sendToClient("\nssh ready to receive..")#time.sleep(1)

cmd = self.receiveFromClient(1024)if len(cmd) == 0:continue

if cmd == 'q':print("quit ssh...")breakretForCmd= Popen(cmd,shell=True,stdout=PIPE).stdout.read()#retForCmd = self.PopenHandle(cmd)

#print("cmd ret:{}".format(retForCmd))

if len(retForCmd) ==0:

retForCmd= b"no data to return!"len1=str(len(retForCmd))

lenghSend="lineSize:%s"%(len1)

self.sendToClient(lenghSend)

time.sleep(1)print("send data size is : {}".format(lenghSend))

clientRet= self.receiveFromClient(100)if clientRet == "readyToGo":#retForCmd = "%s"%retForCmd

#retForCmd = retForCmd.decode()

self.request.sendall(retForCmd)#.requestsendall(retForCmd)

print(retForCmd)defPopenHandle(self,str):

retResult= Popen(str,shell=True,stdout=PIPE).stdout.read()returnretResultdefuserlogin(self,username,password,msgDict):'''用户登陆

:param username:账户名

:param password: 口令

:param msgDict: 账户字典 {username:[口令,磁盘目录名,磁盘配额(MB)]}

:return: isLogin,username,directory,quota'''

#print(AdminMsgList[0][0],AdminMsgList[1][0],AdminMsgList)

isLogin =Falsefor k,v inmsgDict.items():if k == username and msgDict[k][0] ==password:

isLogin=True

directory= msgDict[k][1]

quota= msgDict[k][2]returnisLogin,username,directory,quotaelse:return isLogin,'','',''

defcmd(self,cmdStr):'''接收一个ssh命令

:param cmdStr: 命令

:return: 命令之后的结果'''ret= Popen(cmdStr,shell=True,stdout =PIPE).stdout.read()print(ret)returnretdefputFile(self,obj,fileName):'''写文件:从客户端传来的文件

:return:'''srcfileMD5= ''drcfileMD5= ''

whileTrue:

f= open(fileName,'ab')#--------------------------以累加的形式ab设置文件句柄

#print("1")

long = obj.recv(100)#-------------------------------------------------------------------------recv 所传的长度,用于写入

print(long)

slong= str(long,'utf8')if slong == 'alldone':#---------------------------------传输完毕的处理

drcfileMD5 = self.file_md5(fileName)#上传完成的文件MD5值

if srcfileMD5 == drcfileMD5:#与客户端文件的MD5比较

print("file download is done !")#相等,则下载成功

else:print('file download is failure !')#不等,下载失败

breakilong=int(slong)

obj.sendall(b'ok')#------------------------------------------------------------------------send 回应所传来的信息长度

data = obj.recv(ilong) #--------------------------------------------------------------------recv 以传来的长度设置接收长度,开始接收数据

f.write(data)#写传来的数据到文件

f.close()#关闭文件,之所以在循环里面打开,关闭文件是为了保证每次数据都能存下,便于以后断点续传。

obj.sendall(b"getline")#------------------------------------------------------------------send 回应获取了一行数据

#data1 = str(data,'utf-8')

msg = obj.recv(500)#-----------------------------------------------------------------------recv 接收一个信息,包含:所传文件的总大小,断点位置和MD5值

#print (slong,msg)

msg1= str(msg,'utf8')

isMsg= msg1.split('|')#print(type(data))

if isMsg[0] == 'msg':#获取所传文件的总大小,断点位置和MD5值

filesize = int(isMsg[1])

fileBreak= int(isMsg[2])

srcfileMD5= isMsg[3]

self.progressBar(fileBreak,filesize,"finish :")#---------------------进度条

#lineSize += len(data)

obj.sendall(b"getMsg")#-----------------------------------------------------------------send 回应接收到msg

#---------------------------------------------------------------------------------------------------------------继续循环

#done = obj.recv(100)

defgetFile(self,srcFileName,sizeBreakpointFile,srcFileSizeCount,MD5):'''读文件:获取一个需要下载的文件 get file to download

:param srcFileName:准备要下载的源文件:

:param sizeBreakpointFile:存放断点位置的文件:

:param srcFileSizeCount:源文件的readline总计数

:param:MD5:源文件的MD5值

:return:'''

#print(srcFileName)

breakpointAt = 0 #初始化断点位置

#开始传输文件

t = os.path.isfile(sizeBreakpointFile)#如果存放断点的文件存在,先把他删除,以便从下一个断点往下记

ift:

os.remove(sizeBreakpointFile)

isFile= os.path.isfile(srcFileName)#查看需要下载的文件是否存在

#如果需要下载的源文件存在,就开始get的动作

ifisFile:

srcRf= open(srcFileName,'rb')#获取源文件句柄

while breakpointAt < srcFileSizeCount:#不断记录断点位置,并对比源文件总计数。以防止出现异常中断

#yield

line = srcRf.readline() #---------------源文件读一行

l =len(line)

sl=str(l)

self.request.sendall(bytes(sl,'utf8'))#----------------------------------------------------------------send 发送一行信息的长度

for i in range(200):pass

#print(sl)

self.request.recv(100)#---------------------------------------------------------------------------------recv 等待回应,不做处理

#time.sleep(0.1)

self.request.sendall(line)#发给客户端一行--------------------------------------------------------------send 发送一行信息

self.request.recv(200)#接收一个 get返回信息-------------------------------------------------------------recv 等待回应,不做处理

breakAtf = open(sizeBreakpointFile,'a')#打开记录断点的文件句柄

breakpointAt += 1#断点计数

s =str(breakpointAt)

s= "%s\n"%s

breakAtf.write(s)#写断点位置计数--------------------------写一个断点

breakAtf.close()#关闭句柄

msg= "msg|{}|{}|{}".format(srcFileSizeCount,breakpointAt,MD5)#----------msg|源文件总数|断点位置|MD5

self.request.sendall(bytes(msg,'utf8'))#----------------------------------------------------------------send 发送 msg|源文件总数|断点位置|MD5

self.request.recv(200)#----------------------------------------------------------------------------------rece 等待回应,不做处理

#word = " [正在传输 %s]"%srcFileName

self.progressBar(s,srcFileSizeCount,"finish:") #--------------------进度条

else:

srcRf.close()#-------------------------------------------------------------------------------------------传输完成

self.request.sendall(bytes('alldone','utf8'))#---------------------------------------------------------send ‘alldone’传输完成标志

defgetBreakFile(self,srcFileName,sizeBreakpointFile,breakpointAt,srcFileSizeCount,MD5):'''源文件断点续传

:param srcFileName:

:param sizeBreakpointFile:

:param breakAt:

:param countAll:

:return:'''t= os.path.isfile(sizeBreakpointFile)#如果存放断点的文件存在,先把他删除,以便从下一个断点往下记

ift:

os.remove(sizeBreakpointFile)

isFile= os.path.isfile(srcFileName)#查看需要下载的文件是否存在

i =0#如果需要下载的源文件存在,就开始get的动作

ifisFile:

srcRf= open(srcFileName,'rb')#获取源文件句柄

while i < srcFileSizeCount:#不断记录断点位置,并对比源文件总计数。以防止出现异常中断

i += 1#断点计数

if i > breakpointAt:#进入断点续传条件

line = srcRf.readline() #源文件读一行

self.request.sendall(line)#发给客户端一行---------------------------------------------------------------send

self.request.recv(200)#接收一个 get返回信息--------------------------------------------------------------recv

breakAtf = open(sizeBreakpointFile,'a')#打开记录断点的文件句柄

#drcWf = open(drcFileName,'ab')

#drcWf.write(line)#写目标文件

s =str(breakpointAt)

s= "%s\n"%s#print(breakpointAt)

breakAtf.write(s)#写断点位置计数

breakAtf.close()#drcWf.close()

msg = "msg|{}|{}".format(srcFileSizeCount,breakpointAt)#发送 msg|源文件总数|断点位置

self.request.sendall(bytes(msg,'utf8'))#----------------------------------------------------------------send

self.request.recv(200)#----------------------------------------------------------------------------------rece get

word = "[正在传输 %s]"%srcFileName

self.progressBar(s,srcFileSizeCount,word)#进度条

srcRf.close()#-----------------------------------------------------------------------------------------------传输完成

lastMsg = "alldone|{}".format(MD5)#------------------------------------------------------------------------send 最后发送源文件的MD5值

self.request.sendall(bytes(lastMsg,'utf8'))deffile_md5(self,filename):#calltimes = 0

hmd5 =hashlib.md5()

fp= open(filename,"rb")

f_size=os.stat(filename).st_sizeif f_size>_FILE_SLIM:while(f_size>_FILE_SLIM):

hmd5.update(fp.read(_FILE_SLIM))

f_size/=_FILE_SLIM#calltimes += 1 #delete

if(f_size>0) and (f_size<=_FILE_SLIM):

hmd5.update(fp.read())else:

hmd5.update(fp.read())returnhmd5.hexdigest()defwriteFileSize(self,fileName,sizeFile):

sizeWf= open(sizeFile,'w+')#文件总大小文件开启 ,准备读

count =0

with open(fileName,'rb') as srcRf:#循环以获取文件总数

for line insrcRf:

count+= 1s= str(count)#存储总数到文件 1.txt

s = "%s\n"%s

sizeWf.write(s)

sizeWf.close()returncountdefgetBreakAT(self,fileName):

i=0

with open(fileName,'r') as srcRf:#循环以获取文件总数

for line insrcRf:

lastRead=line#print(type(lastRead))

i=int(lastRead.strip())returnidef progressBar(self,num=1, sum=100,bar_word=":"):

rate= float(num) /float(sum)

rate_num= int(rate * 100)

temp= '\r%d %% %s' %(rate_num,bar_word)

sys.stdout.write(temp)

sys.stdout.flush()##################################

classclsSocketServer(object):def __init__(self,host,port):

self.host=host

self.port=portdefstartServer(self,obj):

server=socketserver.ThreadingTCPServer((self.host,self.port),obj)

server.serve_forever()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值