博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python自动化开发从浅入深-进阶(socketServer)
阅读量:5172 次
发布时间:2019-06-13

本文共 40527 字,大约阅读时间需要 135 分钟。

socketserver:
   --- 每一个连接过来都会单独创建一个线程。
   ---socketserver处理的线程数目与服务器资源配置有关
socketserver有四个基本的类:
  --- TCPServer
  ---UDPServer
  ---UnixStreamServer
  ---UnixDatagramServer
这四个类的同步请求,每一个请求只有完成后才能进行下一个请求。不适合进行长时间的大数据计算,所以需要单独创建进程或线程来处理每个请求。ForkingMixIn和ThreadingMixIn通常被用于支持异步的行为。
5个类的继承关系如下图:

 

我们常用的类是:

ThreadingTCPServer

ThreadingUDPServer

ForkingTCPServer

ForkingUDPServer

一个简单例子:import socketserverclass MyTCHHandler(socketserver.BaseRequestHandler):    #当socketserver创建实例并运行后,便在这里进行通信处理    def handle(self):        passif __name__ == '__main__':    HOST,PORT = 'localhost',5007#创建socketserver实例,将参数及MyTCPHandler传进去server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)#启动server,此时server将一直运行server.serve_forever()

 完整实例:

#!/usr/bin/env python#__author__:ZhaoHong# -*- coding: utf-8 -*-import socketserverimport time,os,sys,re,hashlibfrom subprocess import PIPE,Popenfrom multiSocketFTP.multiFTPServer.set import setting_FILE_SLIM = (100*1024*1024) # 100MBclass FTPServerHandle(socketserver.BaseRequestHandler):    '''      It's a class for handle FTPServer.      socketserver is a multthreading base class,    '''    def handle(self):        while True:            ########## -------------------------------------------------------------------------------------------------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) if t: 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 def receiveFromClient(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') return self.data def sendToClient(self,str): self.request.sendall(bytes(str,'utf-8')) def sshHandle(self): while True: self.sendToClient("\nssh ready to receive..") #time.sleep(1) cmd = self.receiveFromClient(1024) if len(cmd) == 0:continue if cmd == 'q': print("quit ssh...") break retForCmd = 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) def PopenHandle(self,str): retResult = Popen(str,shell=True,stdout=PIPE).stdout.read() return retResult def userlogin(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 = False for k,v in msgDict.items(): if k == username and msgDict[k][0] == password: isLogin = True directory = msgDict[k][1] quota = msgDict[k][2] return isLogin,username,directory,quota else: return isLogin,'','','' def cmd(self,cmdStr): ''' 接收一个ssh命令 :param cmdStr: 命令 :return: 命令之后的结果 ''' ret = Popen(cmdStr,shell=True,stdout =PIPE).stdout.read() print(ret) return ret def putFile(self,obj,fileName): ''' 写文件:从客户端传来的文件 :return: ''' srcfileMD5 = '' drcfileMD5 = '' while True: 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 !')#不等,下载失败 break ilong = 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) def getFile(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)#如果存放断点的文件存在,先把他删除,以便从下一个断点往下记 if t: os.remove(sizeBreakpointFile) isFile = os.path.isfile(srcFileName)#查看需要下载的文件是否存在 #如果需要下载的源文件存在,就开始get的动作 if isFile: 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’传输完成标志 def getBreakFile(self,srcFileName,sizeBreakpointFile,breakpointAt,srcFileSizeCount,MD5): ''' 源文件断点续传 :param srcFileName: :param sizeBreakpointFile: :param breakAt: :param countAll: :return: ''' t = os.path.isfile(sizeBreakpointFile)#如果存放断点的文件存在,先把他删除,以便从下一个断点往下记 if t: os.remove(sizeBreakpointFile) isFile = os.path.isfile(srcFileName)#查看需要下载的文件是否存在 i = 0 #如果需要下载的源文件存在,就开始get的动作 if isFile: 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')) def file_md5(self,filename): #calltimes = 0 hmd5 = hashlib.md5() fp = open(filename,"rb") f_size = os.stat(filename).st_size if 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()) return hmd5.hexdigest() def writeFileSize(self,fileName,sizeFile): sizeWf = open(sizeFile,'w+')#文件总大小文件开启 ,准备读 count = 0 with open(fileName,'rb') as srcRf:#循环以获取文件总数 for line in srcRf: count += 1 s = str(count)#存储总数到文件 1.txt s = "%s\n"%s sizeWf.write(s) sizeWf.close() return count def getBreakAT(self,fileName): i = 0 with open(fileName,'r') as srcRf:#循环以获取文件总数 for line in srcRf: lastRead = line #print(type(lastRead)) i = int(lastRead.strip()) return i def 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()##################################class clsSocketServer(object): def __init__(self,host,port): self.host = host self.port = port def startServer(self,obj): server = socketserver.ThreadingTCPServer((self.host,self.port),obj) server.serve_forever()
完整实例server端
#!/usr/bin/env python#__author__:ZhaoHong# -*- coding: utf-8 -*-import socket,time,os,sys,hashlibfrom multiSocketFTP.multiFTPServer.set import setting#from socket_FTPClient.bin import main_FILE_SLIM = (100*1024*1024) # 100MB##################################class clsSocketClient(object):    def __init__(self,host,port):        '''        init to get :host,port        :param host:        :param port:        :return:        '''        self.host = host        self.port = port    def myConnect(self):        '''        连接到服务器 conn to server        :return:        '''        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)        s.connect((self.host,self.port))        return s    def receiveFromServer(self,obj,length):        '''        接收信息 receive from server        :param obj:        :param length:        :return:        '''        data = obj.recv(length).strip()#waiting for receiv message,it's can get 1024 character one time        if isinstance(data,bytes):            try:                data = str(data,'gbk')            except:                data = str(data,'utf-8')        return data    def sendToServer(self,obj,str):        '''        send message to server        :param obj:        :param str:        :return:        '''        obj.sendall(bytes(str,'utf-8'))    def login(self,objSocket):        '''        登录处理 user login handle        :param objSocket:        :return:        '''        cmdLogin = input("input<<< login user password>>> ").strip()#Login command input        loginCmd = cmdLogin.split()        if loginCmd[0] == 'q':return 'quit',''        if loginCmd[0]=='login' and len(loginCmd) == 3:#judge : is "login" string and two blank space            self.sendToServer(objSocket,"{} {} {}".format(loginCmd[0],loginCmd[1],loginCmd[2]))            loginISVerification = self.receiveFromServer(objSocket,1024)            return loginISVerification,loginCmd[1]    def cmdHandle(self,objSocket,user):        '''        ssh 命令处理  command handle here        :param objSocket:        :param user:        :return:        '''        print("{} login success!".format(user))        while True:#begin to waiting input FTP command            cmdGet = input("FTP command here>>> ").strip()#FTP command input            if len(cmdGet) == 0 : continue #if FTP command is blank then continue            head = cmdGet.split()            if (head[0] == "cd" and len(head) == 2) or \               (head[0] == "ls" and len(head) >= 1)  or \                    (head[0] == "dir" and len(head) >= 1):                self.sendToServer(objSocket,cmdGet)#--------------------------------------------------------------------send FTP cmd                time.sleep(1)                ret = self.receiveFromServer(objSocket,1024)#-----------------------------------------------------------rev                print(ret)                #self.sendToServer(objSocket,"OK")            elif (head[0] == "get" and len(head) >= 2):#--------------------------------------------------------------get                print("start downloading")                self.sendToServer(objSocket,cmdGet)#--------------------------------------------------------------------send get cmd 发送一个命令给服务端                if setting.sysStr == "Windows":                    fileName = "{}{}\\{}".format(setting.homeDIR,head[4],head[2])                else:                    fileName = "{}{}/{}".format(setting.homeDIR,head[4],head[2])                    #fileName = "{}/{}".format(setting.homeDIR,head[1])                t = os.path.isfile(fileName)                if t:                    print(fileName)                    fileMD5 = self.file_md5(fileName)                    s = "MD5|{}".format(fileMD5)                    objSocket.recv(200)#--------------------------------------------------------------------------------recv b'get'                    objSocket.sendall(bytes(s,'utf-8'))#---------------------------------------------------------------send MD5                    lineSize = 0                    self.writeToFile(objSocket,fileName)                else:                    objSocket.recv(200)#--------------------------------------------------------------------------------recv b'get'---(1)                    objSocket.sendall(b'notHaveFile|a')#--------------------------------------------------------send (notHaveFile)                    self.writeToFile(objSocket,fileName)##########################################################################################################################            elif (head[0] == "put" and len(head) >= 2):                print("start upload")                self.sendToServer(objSocket,cmdGet)                if setting.sysStr == "Windows":                    pathFile = "%s%s\\%s"%(setting.homeDIR,head[3],head[1])                    saveSizeFile = "%s%s\\%s"%(setting.homeDIR,head[3],"srcFileSize.dat")                    saveBreakFile = "%s%s\\%s"%(setting.homeDIR,head[3],"breakAt.dat")                else:                    pathFile = "%s%s/%s"%(setting.homeDIR,head[3],head[1])#ftpInput[1]: path,ftpInput[2]:src filename ftpInput[2]: drc filename                    saveSizeFile = "%s%s\\%s"%(setting.homeDIR,head[3],"srcFileSize.dat")                    saveBreakFile = "%s%s\\%s"%(setting.homeDIR,head[3],"breakAt.dat")                objSocket.sendall(b"get")#---------------------------------------------------------------send get                msg = objSocket.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.putFile(objSocket,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("文件已经成功下载")                        objSocket.sendall(b'fileIsdownload')#------------------------------------------send   文件已经下载 fileIsdownload                    else:#否则,进入断点续传                        breakat = self.getBreakAT(pathFile)#获取断点位置数字                        self.putBreakFile(objSocket,pathFile,saveBreakFile,breakat,fileSize,md5Value)#-----------------进入断点续传 function            elif (head[0] == "ssh" and len(head) >= 1):                cmd = ''                for i in range(len(head)):                    if i>0:                        cmd += head[i]                        cmd = cmd.strip()                        print(cmd)                self.sendToServer(objSocket,cmd)                time.sleep(1)                ret = self.receiveFromServer(objSocket,1024)                print(ret)            elif head[0] == "q":                self.sendToServer(objSocket,head[0])                break            else:                self.sendToServer(objSocket,cmdGet)                ret = self.receiveFromServer(objSocket,1024)                #ret = ret[2:-1]                print(ret)        return True    def ssh(self,objSocket):        '''        ssh command>>        :param objSocket:        :return:        '''        self.sendToServer(objSocket,"ssh")        #s.sendall(bytes("ssh",'utf-8'))        time.sleep(1)        sshReady =self.receiveFromServer(objSocket,100)        #sshReady = str(s.recv(100),'utf-8')        print(sshReady)        time.sleep(1)        size = 0        while True:            cmdSSH = input("command >>> ").strip()#------------------------------------------------------输入ssh命令            if len(cmdSSH) == 0:continue            self.sendToServer(objSocket,cmdSSH)#-----------------------------------------------------------send 发出一个ssh命令            retSize = self.receiveFromServer(objSocket,100)#-----------------------------------------------recv 接收大小标志            sizeMsg = str(retSize).split(":")            if sizeMsg[0] == "lineSize":#----------------                print("send ready to go")                size = sizeMsg[1]#----获取大小                time.sleep(1)                self.sendToServer(objSocket,"readyToGo")#----------------------------------------------send 准备好信息                #s.sendall(bytes("readyToGo",'utf-8'))                time.sleep(1)            res =b''            recv_size = 0            while recv_size < int(size):#------------------------循环接收信息,直到收取完毕                sshReturn = objSocket.recv(1024)#-------------------------------------------------------recv 接收返回结果信息                recv_size += len(sshReturn)                res += sshReturn            else:#-----------------------------------------------------------------------------------最后打印返回结果                if setting.sysStr=='Windows':                    res = str(res,'gbk')                else:                    res = str(res,'utf8')                print(res)            if cmdSSH == "q":                self.sendToServer(objSocket,"quit")#------------------------------send 退出信息                break    def putFile(self,obj,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)#如果存放断点的文件存在,先把他删除,以便从下一个断点往下记        if t:            os.remove(sizeBreakpointFile)        isFile = os.path.isfile(srcFileName)#查看需要下载的文件是否存在        #如果需要下载的源文件存在,就开始get的动作        if isFile:            srcRf = open(srcFileName,'rb')#获取源文件句柄            while breakpointAt < srcFileSizeCount:#不断记录断点位置,并对比源文件总计数。以防止出现异常中断                #yield                line = srcRf.readline() #源文件读一行                l = len(line)                sl = str(l)                obj.sendall(bytes(sl,'utf8'))                obj.recv(100)                for i in range(200):                    pass                #print(sl)                obj.sendall(line)# 发给客户端一行---------------------------------------------------------------send                obj.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|源文件总数|断点位置                obj.sendall(bytes(msg,'utf8'))#----------------------------------------------------------------send                obj.recv(200)#----------------------------------------------------------------------------------rece   get                #word = " [正在传输 %s]"%srcFileName                self.progressBar(s,srcFileSizeCount,"finish") #进度条            else:                srcRf.close()#-----------------------------------------------------------------------------------------------传输完成                #lastMsg = "alldone|{}".format(MD5)#------------------------------------------------------------------------send     最后发送源文件的MD5值                obj.sendall(bytes('alldone','utf8'))    def writeToFile(self,obj,fileName):        '''        写入:对get命令的写操作        :param obj: socket对象        :param fileName: 写入的文件名        :return:        '''        srcfileMD5 = ''        drcfileMD5 = ''        while True:            f = open(fileName,'ab')#-----------------以ab方式打开文件句柄            #print("1")            long = obj.recv(100)#---------------------------------------------------------------------------------------recv 接收一个传来的文件信息长度            slong = str(long,'utf8')            if slong == 'alldone':#----------------------传输结束处理                drcfileMD5 = self.file_md5(fileName)                if srcfileMD5 == drcfileMD5:                    print("file download is done !")                else:                    print('file download is failure !')                break            ilong = 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  msg|源文件总数|断点位置|MD5            msg1= str(msg,'utf8')            isMsg = msg1.split('|')            #print(type(data))            if isMsg[0] == 'msg':#处理为 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 回应对端,不做处理            #--------------------------------------------------------------------------------------循环    def progressBar(slef,num=1, sum=100,bar_word=":"):        '''        处理进度条        :param num:        :param sum:        :param bar_word:        :return:        '''        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()    def file_md5(self,filename):         '''          生成文件的MD5值         :param filename:         :return:         '''         #calltimes = 0         hmd5 = hashlib.md5()         fp = open(filename,"rb")         f_size = os.stat(filename).st_size         if 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())         return hmd5.hexdigest()    def writeFileSize(self,fileName,sizeFile):        '''        计算文件的总大小(总计数)        :param fileName:        :param sizeFile:        :return:        '''        sizeWf = open(sizeFile,'w+')#文件总大小文件开启   ,准备读        count = 0        with open(fileName,'rb') as srcRf:#循环以获取文件总数            for line in srcRf:                count += 1        s = str(count)#存储总数到文件 1.txt        s = "%s\n"%s        sizeWf.write(s)        sizeWf.close()        return count    def getBreakAT(self,fileName):        '''        获取文件断点位置        :param fileName:        :return:        '''        i = 0        lastRead = '1'        with open(fileName,'r') as srcRf:#循环以获取文件总数            for line in srcRf:                lastRead = line            #print(type(lastRead))            i = int(lastRead.strip())        return i    def putBreakFile(self,obj,srcFileName,sizeBreakpointFile,breakpointAt,srcFileSizeCount,MD5):        '''        写文件:源文件断点续传        :param srcFileName:        :param sizeBreakpointFile:        :param breakAt:        :param countAll:        :return:        '''        t = os.path.isfile(sizeBreakpointFile)#如果存放断点的文件存在,先把他删除,以便从下一个断点往下记        if t:            os.remove(sizeBreakpointFile)        isFile = os.path.isfile(srcFileName)#查看需要下载的文件是否存在        i = 0        #如果需要下载的源文件存在,就开始get的动作        if isFile:            srcRf = open(srcFileName,'rb')#获取源文件句柄            while i < srcFileSizeCount:#不断记录断点位置,并对比源文件总计数。以防止出现异常中断                i += 1#断点计数                if i > breakpointAt:#进入断点续传条件                    line = srcRf.readline() #源文件读一行                    obj.sendall(line)# 发给客户端一行---------------------------------------------------------------send                    obj.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|源文件总数|断点位置                    obj.sendall(bytes(msg,'utf8'))#----------------------------------------------------------------send                    obj.recv(200)#----------------------------------------------------------------------------------rece   get                    word = " [正在传输 %s]"%srcFileName                    self.progressBar(s,srcFileSizeCount,word) #进度条            srcRf.close()#-----------------------------------------------------------------------------------------------传输完成            lastMsg = "alldone|{}".format(MD5)#-----------------            obj.sendall(bytes(lastMsg,'utf8'))#------------------------------------------------------------------------send     最后发送源文件的MD5值
完整实例client端

 

转载于:https://www.cnblogs.com/whiggzhaohong/p/5321457.html

你可能感兴趣的文章
选择语句 if else
查看>>
STL中的set使用方法详细!!!!
查看>>
sealed关键字的作用
查看>>
Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划
查看>>
HDU - 4472 Count
查看>>
搭建测试环境
查看>>
调用链监控 CAT 之 入门
查看>>
flexbox属性速览及常见布局实现
查看>>
zlib在Linux和windows中的使用
查看>>
rabbitMq实战使用
查看>>
JQuery Easyui/TopJUI表格基本的删除功能(删除当前行和多选删除)
查看>>
javascript 倒计时
查看>>
web前端工程师入门须知
查看>>
linux--->linux 各个文件夹及含义
查看>>
欢迎使用CSD横竖屏切换问题占位
查看>>
2016集训测试赛(二十)Problem B: 字典树
查看>>
中文保存在properties乱码的解决
查看>>
poj题目分类
查看>>
idea 配置mybatis Generator 不显示的解决方案 和 配置MBG
查看>>
英语生疏了,每日至少一句吧
查看>>