最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python 基于selectors庫實(shí)現(xiàn)文件上傳與下載

 更新時(shí)間:2020年12月31日 11:34:49   作者:槑槑的離生  
這篇文章主要介紹了python 基于selectors庫實(shí)現(xiàn)文件上傳與下載的示例代碼,幫助大家更好的理解和使用python,感興趣的朋友可以了解下

server.py

import selectors
import socket
import os
import time


BASE_DIR =os.path.abspath(os.path.dirname(__file__))

class selectFtpserver:
  def __init__(self):
    self.dic = {} # 創(chuàng)建空字典
    self.hasReceived = 0
    self.hasSend=0
    self.sel = selectors.DefaultSelector() # 生成一個(gè)select對象
    self.create_socket() #create_socket()是創(chuàng)建socket對象函數(shù)完成綁定功能
    self.hanle() #handle()函數(shù)完成循環(huán)監(jiān)聽

  def create_socket(self):
    sock = socket.socket()
    sock.bind(('127.0.0.1', 8899))
    sock.listen()
    sock.setblocking(False)
    self.sel.register(sock, selectors.EVENT_READ, self.accept) # 把剛生成的sock連接對象注冊到select連接列表中,并交給accept函數(shù)處理
    print("服務(wù)端已打開,請連接客戶端")

  def hanle(self):
    while True:
      events = self.sel.select() # 默認(rèn)是阻塞,有活動連接就返回活動的連接列表
      # 這里看起來是select,其實(shí)有可能會使用epoll,如果你的系統(tǒng)支持epoll,那么默認(rèn)就是epoll
      # print("event==",events)
      for key, mask in events:
        callback = key.data # 去調(diào)accept函數(shù)
        callback(key.fileobj, mask) # key.fileobj就是readable中的一個(gè)socket連接對象

  def accept(self,sock, mask):
    conn, addr = sock.accept() # Should be ready
    print('accepted', conn, 'from', addr)
    conn.setblocking(False) # 設(shè)定非阻塞
    self.sel.register(conn, selectors.EVENT_READ, self.read) # 新連接注冊read回調(diào)函數(shù)
    self.dic[conn] = {} # 在空字典里進(jìn)行了conn賦值,self.dic={conn:{},}

  def read(self, conn, mask): # 接收了conn和mask
    try: # 加異常防止客戶端突然斷開
      if not self.dic[conn]: # 判斷self.dic[conn]里面是否是空字典,如果是空字典,代表第一次進(jìn)來
        print('====第一次進(jìn)來')
        data = conn.recv(1024) # conn接收了客戶端發(fā)來的數(shù)據(jù)
        print("data==",str(data, encoding='utf-8'))
        cmd, filename,filesize = str(data, encoding='utf-8').split('|') # 把接收到客戶端發(fā)來的包解開拿到cmd,filename,filesize個(gè)信息
        self.dic = {conn: {"cmd": cmd, "filename": filename, "filesize": int(filesize)}} # 把拿到的cmd,filename,filesize信息放到self.dic字典里去后程序返回到handle()函數(shù)里的events繼續(xù)監(jiān)聽
        print(self.dic)
        if cmd == 'put': # 如果接收的信息是put
          conn.send(bytes("OK", encoding='utf8')) # 給客戶端返回一條數(shù)據(jù)
        if self.dic[conn]['cmd'] == 'get':
          file = os.path.join(BASE_DIR, "upload", filename)

          if os.path.exists(file):
            print("文件存在的情況,返回YES給客戶端")
            filesize = os.path.getsize(file)
            self.dic[conn]['filesize'] = filesize
            print("self.dic",self.dic)
            send_info = '%s|%s' % ('YES', filesize)
            conn.send(bytes(send_info, encoding='utf8'))
          else:
            print("文件不存在情況下")
            send_info = '%s|%s' % ('NO', 0)
            conn.send(bytes(send_info, encoding='utf8'))
            self.dic[conn] = {} #文件不存在的情況下,要將清空字典
      else: # 如果不是空字典代表不是第一次進(jìn)來
        print('不是第一次來的')
        print(self.dic)
        if self.dic[conn].get('cmd', None): # 對接收的命令進(jìn)行分發(fā)判斷是put還是get
          cmd = self.dic[conn].get('cmd')
          if hasattr(self, cmd): # 如果cmd=put調(diào)用put函數(shù),如果是cmd=get函數(shù)調(diào)用get函數(shù)
            func = getattr(self, cmd)
            func(conn)
          else:
            print("error cmd!")
            conn.close()
        else:
          print("error cmd!")
          conn.close()
    except Exception as e:
      print('斷開的客戶端信息是:', conn)
      self.sel.unregister(conn) # 如果沒有接收到數(shù)據(jù)做一個(gè)關(guān)閉解除
      conn.close()

    # put上傳函數(shù)
  def put(self, conn):
    fileName = self.dic[conn]['filename']
    fileSize = self.dic[conn]['filesize']
    # print("BASE_DIR",BASE_DIR)
    path = os.path.join(BASE_DIR, "upload", fileName) # 拿到要接收的信息
    # print(fileName,fileSize,path)

    recv_data = conn.recv(1024) # 接收客戶端上傳的數(shù)據(jù)1024字節(jié)
    self.hasReceived += len(recv_data) # 把接收的數(shù)據(jù)累加到變量self.hasReceived

    with open(path, 'ab') as f: # 打開文件
      f.write(recv_data) # 把接收的數(shù)據(jù)寫到文件里去

    if fileSize == self.hasReceived: # 判斷文件大小跟接收大小是否一樣
      if conn in self.dic.keys(): # 如果文件大小跟接收大小一樣清空字典
        self.dic[conn] = {}
      self.hasReceived = 0 #S上傳結(jié)束之后,需要將self.hasReceived 重置成功
      print("%s 上傳完畢!" % fileName)

  def get(self,conn):
    fileName = self.dic[conn]['filename']
    file = os.path.join(BASE_DIR, "upload", fileName)
    # fileSize = os.path.getsize(file)
    fileSize=self.dic[conn]['filesize']

    data = conn.recv(1024) # conn接收了客戶端發(fā)來的數(shù)據(jù)
    dataOK = str(data, encoding='utf-8')

    if dataOK == 'OK':
      with open(file, 'rb') as f: # 打開文件
        while fileSize > self.hasSend: # 循環(huán)的發(fā)送文件給客戶端
          contant = f.read(1024)
          recv_size = len(contant)
          conn.send(contant)
          self.hasSend += recv_size
          s = str(int(self.hasSend / fileSize * 100)) + "%"
          print("正在下載文件: " + fileName + " 已經(jīng)下載:" + s)

      if fileSize == self.hasSend: # 判斷文件大小跟接收大小是否一樣
        if conn in self.dic.keys(): # 如果文件大小跟接收大小一樣清空字典
          self.dic[conn] = {}
        print("%s 下載完畢!" % fileName)
        self.hasSend = 0

if __name__ == '__main__':
  selectFtpserver()

client.py

import socket
import os,sys
BASE_DIR=os.path.dirname(os.path.abspath(__file__))

class selectFtpClient:
  def __init__(self):
    self.args=sys.argv               #sys.argv在命令行輸入的參數(shù),第一個(gè)參數(shù)默認(rèn)文件名,第二個(gè)參數(shù)跟IP地址和端口
    if len(self.args)>1:              #如果大于1把第二個(gè)參數(shù)倆個(gè)值賦值給port
      self.port=(self.args[1],int(self.args[2]))
    else:
      self.port=("127.0.0.1",8899)        #如果沒有第二個(gè)參數(shù)默認(rèn)取這個(gè)
    self.create_socket()               #
    self.command_fanout()              #進(jìn)行命令分發(fā)
    self.mainPath = os.path.join(BASE_DIR, 'filename') # 獲取該客戶端下的filename路徑

  #create_socket函數(shù)創(chuàng)建socket對象連接服務(wù)端
  def create_socket(self):
    try:
      self.sk = socket.socket()
      self.sk.connect(self.port)
      print('連接FTP服務(wù)器成功!')
    except Exception as e:
      print("eroor:",e)

  #command_fanout()函數(shù)進(jìn)行命令分發(fā)
  def command_fanout(self):
    while True:
      try:
        print("----------------welcome to ftp client-------------------")
        self.help_info()
        cmd_info = input('>>>請輸入操作命令:').strip() # put 12.png images
        if not cmd_info:
          continue
        cmd,file = cmd_info.split() ##按照空格分隔
        # print("命令是什么", cmds)
        if cmd == "quit":
          break
        if hasattr(self, cmd):
          func = getattr(self, cmd)
          func(cmd,file)
          Tag = input("是否繼續(xù)進(jìn)入ftp clinet,請選擇Y/N:").strip()
          if Tag.upper() == 'Y':
            continue
          else:
            break
        else:
          print('No such command ,please try again')
      except Exception as e: # server關(guān)閉了
        print('%s' % e)
        break

  def help_info(self):
    print ('''
       get + (文件名)  表示下載文件
       put + (文件名)  表示上傳文件
       quit       表示退出登錄
    ''')

  #put()上傳函數(shù)
  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) #給文件名字大小打包成fileInf
      self.sk.send(bytes(fileInfo, encoding='utf8')) #調(diào)用send方法把fileInf發(fā)給服務(wù)端
      recvStatus = self.sk.recv(1024)         #接收服務(wù)端返回的OK內(nèi)容
      print('recvStatus' , recvStatus)
      hasSend = 0
      if str(recvStatus, encoding='utf8') == "OK":  #如果接收到服務(wù)端返回的OK
        with open(file, 'rb') as f:        #打開文件
          while fileSize > hasSend :       #循環(huán)的去上傳文件
            contant = f.read(1024)
            recv_size = len(contant)
            self.sk.send(contant)
            hasSend += recv_size
            s=str(int(hasSend/fileSize*100))+"%"
            print("正在上傳文件: "+fileName+" 已經(jīng)上傳:" +s)
        print('%s文件上傳完畢' % (fileName,))
    else:
      print('要上傳的文件不存在')

  #get()下載函數(shù)
  def get(self,cmd,fileName):
    path = os.path.join(BASE_DIR, "download", fileName) # 拿到要接收的信息
    fileSize=0
    fileInfo = '%s|%s|%s' % (cmd, fileName, fileSize) # 給文件名字大小打包成fileInf
    print(fileInfo)
    self.sk.send(bytes(fileInfo, encoding='utf8')) # 調(diào)用send方法把fileInfo發(fā)給服務(wù)端

    recvdata = self.sk.recv(1024) # 接收服務(wù)端返回的是否存在文件內(nèi)容
    recvStatus, fileSize = str(recvdata, encoding='utf-8').split('|')
    print("recvStatus==",recvStatus,fileSize)
    fileSize = int(fileSize)

    hasReceived = 0
    if recvStatus == "YES": # 如果接收到服務(wù)端返回的YES
      self.sk.send(bytes('OK', encoding='utf8')) # 通知服務(wù)端可以正常下載了

      while fileSize > hasReceived: # 循環(huán)的發(fā)送文件給客戶端
        recv_data = self.sk.recv(1024) # 接收客戶端上傳的數(shù)據(jù)1024字節(jié)
        hasReceived += len(recv_data) # 把接收的數(shù)據(jù)累加到變量self.hasReceived
        print("hasReceived",hasReceived)

        with open(path, 'ab') as f: # 打開文件
          f.write(recv_data) # 把接收的數(shù)據(jù)寫到文件里去

        if fileSize == hasReceived: # 判斷文件大小跟接收大小是否一樣
          print("%s 下載完畢!" % fileName)
          recvStatus = 'YESS'
    else:
       print('要下載的文件不存在')


if __name__=='__main__':
  selectFtpClient()

以上就是python 基于selectors庫實(shí)現(xiàn)文件上傳與下載的詳細(xì)內(nèi)容,更多關(guān)于python 上傳下載的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python量化交易詳細(xì)簡介

    Python量化交易詳細(xì)簡介

    這篇文章主要介紹了Python量化交易詳細(xì),??算法交易是使用自動化系統(tǒng)來執(zhí)行交易,這些交易是通過特定的算法以預(yù)測的方式執(zhí)行的沒有任何人為干預(yù)。依據(jù)數(shù)學(xué)模型對大數(shù)據(jù)進(jìn)行概率分析,使得長期收益期望最大化,下文詳細(xì)敘述,需要的朋友可以參考一下
    2022-03-03
  • python?opencv的imread方法無法讀取圖片問題

    python?opencv的imread方法無法讀取圖片問題

    這篇文章主要介紹了python?opencv的imread方法無法讀取圖片問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 在Python IDLE 下調(diào)用anaconda中的庫教程

    在Python IDLE 下調(diào)用anaconda中的庫教程

    這篇文章主要介紹了在Python IDLE 下調(diào)用anaconda中的庫教程,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • 基于Python實(shí)現(xiàn)絲滑換裝視頻剪輯

    基于Python實(shí)現(xiàn)絲滑換裝視頻剪輯

    看到人家用PR什么編輯軟件做這種絲滑一鍵換裝的視頻,自己也想嘗試一下。不過PR這破玩意太難用了,還不如敲代碼來的省事。所以本文將利用Python算法實(shí)現(xiàn)絲滑換裝視頻,感興趣的可以了解一下
    2022-04-04
  • Python單鏈表簡單實(shí)現(xiàn)代碼

    Python單鏈表簡單實(shí)現(xiàn)代碼

    這篇文章主要介紹了Python單鏈表簡單實(shí)現(xiàn)代碼,結(jié)合實(shí)例形式分析了Python單鏈表的具體定義與功能實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-04-04
  • Python中工作日類庫Busines Holiday的介紹與使用

    Python中工作日類庫Busines Holiday的介紹與使用

    Python語言是通過區(qū)分類庫的方式來劃分功能。用戶根據(jù)自身的需要加載合適的類庫,來完成需要的功能。下面這篇文章主要給大家介紹了關(guān)于Python中工作日類庫Busines Holiday使用的相關(guān)資料,需要的朋友可以參考借鑒。
    2017-07-07
  • Python3內(nèi)置模塊pprint讓打印比print更美觀詳解

    Python3內(nèi)置模塊pprint讓打印比print更美觀詳解

    這篇文章主要給大家介紹了關(guān)于Python3內(nèi)置模塊pprint讓打印比print更美觀的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Python3具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • Python使用tkinter制作在線翻譯軟件

    Python使用tkinter制作在線翻譯軟件

    這篇文章主要為大家詳細(xì)介紹了Python使用tkinter制作在線翻譯軟件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-02-02
  • 最新python下載安裝及環(huán)境搭建教程

    最新python下載安裝及環(huán)境搭建教程

    最近小編收到了好多小伙伴的吐槽稱不會下載安裝python,博主聽到后非常的扎心,經(jīng)過博主幾天的熬夜加班,給大家出了一套python下載安裝以及pycharm環(huán)境搭建的完整教程,一起來看看吧
    2024-02-02
  • python中map的基本用法示例

    python中map的基本用法示例

    map函數(shù)的原型是map(function, iterable, …),它的返回結(jié)果是一個(gè)列表。下面這篇文章主要給大家介紹了關(guān)于python中map的基本用法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-09-09

最新評論

德昌县| 肇州县| 炉霍县| 合水县| 杭州市| 文登市| 沁水县| 新巴尔虎右旗| 金湖县| 聂荣县| 蓝田县| 镇巴县| 德江县| 蛟河市| 伽师县| 洛隆县| 太湖县| 平顺县| 阳西县| 宽甸| 九江县| 山东省| 资讯 | 武城县| 康乐县| 吴川市| 基隆市| 重庆市| 凤城市| 海兴县| 华安县| 阜阳市| 潜江市| 会泽县| 阿坝| 宁城县| 克东县| 金秀| 原阳县| 桦川县| 汉中市|