咱們經常使用的類是:python
ThreadingTCPServerlinux
ThreadingUDPServershell
ForkingTCPServerwindows
ForkingUDPServer服務器
一個簡單例子: import socketserver class MyTCHHandler(socketserver.BaseRequestHandler): #當socketserver建立實例並運行後,便在這裏進行通訊處理 def handle(self): pass if __name__ == '__main__': HOST,PORT = 'localhost',5007 #建立socketserver實例,將參數及MyTCPHandler傳進去 server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler) #啓動server,此時server將一直運行 server.serve_forever()
完整實例:ssh
#!/usr/bin/env python #__author__:ZhaoHong # -*- coding: utf-8 -*- import socketserver import time,os,sys,re,hashlib from subprocess import PIPE,Popen from multiSocketFTP.multiFTPServer.set import setting _FILE_SLIM = (100*1024*1024) # 100MB class 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 <send > 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 <send> 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('<login failure>') 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()
#!/usr/bin/env python #__author__:ZhaoHong # -*- coding: utf-8 -*- import socket,time,os,sys,hashlib from 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值