1. 程式人生 > >day29 socketsever ftp知識點講解

day29 socketsever ftp知識點講解

  1. socketsever

# 客戶端
import socketserver

class KnightSever(socketserver.BaseRequestHandler): # 固定寫法

    def handle(self):
        # self.request()  相當於conn通道
        while 1:
            from_client_msg = self.request.recv(1024)   #接收客戶端資訊
            print(from_client_msg.decode('
utf-8')) sever_msg = input('服務端>>>') self.request.send(sever_msg.encode('utf-8')) # 傳送服務端資訊 if __name__ == '__main__': ip_port = ('127.0.0.1', 8001) sever = socketserver.ThreadingTCPServer(ip_port, KnightSever) sever.serve_forever() # 讓伺服器永久執行 # 客戶端 import
socket client = socket.socket() client.connect(('127.0.0.1', 8001)) while 1: client_data = input('別開車') client.send(client_data.encode('utf-8')) from_sever_msg = client.recv(1024) print(from_sever_msg.decode('utf-8')) client.close()
socketsever演示

   模組的原始碼分析:

查詢屬性的順序:ThreadingTCPServer->ThreadingMixIn->TCPServer->BaseServer

例項化得到server,先找ThreadMinxIn中的__init__方法,發現沒有init方法,然後找類ThreadingTCPServer的__init__,在TCPServer中找到,在裡面建立了socket物件,進而執行server_bind(相當於bind),server_active(點進去看執行了listen)
找server下的serve_forever,在BaseServer中找到,進而執行self._handle_request_noblock(),該方法同樣是在BaseServer中
執行self._handle_request_noblock()進而執行request, client_address = self.get_request()(就是TCPServer中的self.socket.accept()),然後執行self.process_request(request, client_address)
在ThreadingMixIn中找到process_request,開啟多執行緒應對併發,進而執行process_request_thread,執行self.finish_request(request, client_address)
上述四部分完成了連結迴圈,本部分開始進入處理通訊部分,在BaseServer中找到finish_request,觸發我們自己定義的類的例項化,去找__init__方法,而我們自己定義的類沒有該方法,則去它的父類也就是BaseRequestHandler中找....
原始碼分析總結:

基於tcp的socketserver我們自己定義的類中的
  self.server即套接字物件
  self.request即一個連結
  self.client_address即客戶端地址
基於udp的socketserver我們自己定義的類中的   self.request是一個元組(第一個元素是客戶端發來的資料,第二部分是服務端的udp套接字物件),如(b'adsf', <socket.socket fd=200, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('127.0.0.1', 8080)>)   self.client_address即客戶端地址


2. 字串操作以及列印 —— 實現上傳下載的進度條功能
# 進度條列印
一、
    import sys
    import time
    for i in range(50):
        sys.stdout.write('>')
        sys.stdout.flush()
        time.sleep(0.2)

二、
    #總共接收到的大小和總檔案大小的比值:
    #all_size_len表示當前總共接受的多長的資料,是累計的
    #file_size表示檔案的總大小
        per_cent = round(all_size_len/file_size,2) #將比值做成兩位數的小數
    #通過\r來實現同一行列印,每次列印都回到行首列印
        print('\r'+ '%s%%'%(str(int(per_cent*100))) + '*'*(int(per_cent*100)),end='')  #由於float型別的資料沒法通過%s來進行字串格式化,所以我在這裡通過int來轉換了一下,並用str轉換了一下,後面再拼接上*,這個*的數量根據現在計算出來的比值來確定,就能夠出來%3***這樣的效果。自行使用上面的sys.stdout來實現一下這個直接print的效果。