1. 程式人生 > >老男孩14期自動化運維day8隨筆和作業(多使用者線上的輕量級ftpserver)

老男孩14期自動化運維day8隨筆和作業(多使用者線上的輕量級ftpserver)

1.ftp server 的執行流程:
(1)讀取客戶端發過來的檔名
(2)檢測檔案是否存在
(3)開啟檔案
(4)檢測檔案大小
(5)傳送檔案大小和md5給客戶端
(6)等待客戶端確認
(7)開始邊讀邊發
(8)傳送md5

2.粘包問題
什麼是粘包:兩條send 挨著 容易被當成一條send (linux 上這種問題比較明顯 )

3.socketserver(實現多個請求併發)
(1)你必須自己建立一個請求處理類,並且這個類要繼承BaseRequestHandler,並且重寫父類裡的handle()方法
(2)你必須例項化一個TCPServer,並且傳遞serverip和你剛建立的請求處理類給這個TCPServer
(3)上面例項化的server,server.handle_request() # 只處理一個請求(用的少)
server.serve_forever() # 處理多個請求,永遠執行,直到shut down。

0.0.0.0 是無論哪個ip地址都可以連上 有些時候一個主機可以有多個網絡卡,一個網絡卡對應一個或多個ip,所以會有多個ip
以下為多併發socketserver 基本寫法:

import socketserver


# 多併發socketserver基本寫法
class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):# 跟客戶端每個請求都在handle 父類裡handle() 為空

        while True:
            try:
                self.
data=self.request.recv(1024).strip() # 必須要是self.request print("{} wrote:".format(self.client_address[0])) print(self.data) # if not self.data: # 客戶端斷了之後 python2.x 是斷開沒有異常的 3.x有自帶的異常 要抓住 # print(self.client_address,"斷開了") # break
self.request.send(self.data.upper()) except ConnectionError as e: print(e) break if __name__=='__main__': HOST,PORT="localhost",9999 # 多併發 server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler) # 多執行緒處理請求 # server=socketserver.ForkingTCPServer((HOST,PORT),MyTCPHandler) 多程序處理請求, windows用不了 # 單個請求 # server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) 簡化版單個請求 server.serve_forever()

4.基於socket的減半ssh server
sock_server_ssh.py
注意有個坑:要獲得傳輸資料的位元組數 ,一箇中文3個位元組,一個英文1個位元組,比如帶有中文的string a,send 要這樣寫 send( str ( len(a.encode) ).encode()。因為第一個a.encode 是把字串轉換為byte 再len(byte)得到位元組大小(為整數),整數不能直接encode,必須先轉換為字串再encode()。

#!/usr/bin/env python
# coding:utf-8
# Author:Yang
# 減半ssh

import socket,os
server=socket.socket()
server.bind(('localhost',9999))
server.listen()

while True:
    conn,addr=server.accept()
    print("new conn",addr)
    while True:
        print("等待連線")
        data=conn.recv(1024)
        if not data:
            print("客戶端已斷開...")
            break
        print("執行指令",data)
        cmd_res=os.popen(data.decode()).read() # 接收字串 執行結果也是字串
        print("before send",len(cmd_res))
        if len(cmd_res)==0:
            cmd_res="cmd has no output..."
        conn.send(str(len(cmd_res.encode())).encode("utf-8"))  # lenth 是整數 不能直接encode 所以要先str 在encode
        # 這是一個坑:注意上面len(cmd_res.encode()) 因為len("中")為1,必須要再encode才能獲得位元組數 ,一箇中文三個位元組!!
        # time.sleep(0.5)
        client_ack=conn.recv(1024) # wit client to confirm  這個方法用來防止socket粘包

        conn.send(cmd_res.encode("utf-8"))

server.close

sock_client_ssh.py

#!/usr/bin/env python
# coding:utf-8
# Author:Yang

import  socket

client=socket.socket()
client.connect(("localhost",9999))

while True:
    cmd = input(">>:").strip()
    if len(cmd)==0:
        continue

    client.send(cmd.encode("utf-8"))

    cmd_res_size = client.recv(1024) # 接收命令結果的長度
    print("命令結果大小",cmd_res_size)
    client.send("準備好接受了".encode("utf-8"))
    received_size=0
    received_data=b''
    while received_size < int(cmd_res_size.decode()):
        data=client.recv(1024)
        received_size+=len(data) # 每次收到的有可能小於1024 所以必須用len判斷
        received_data+=data
        print(received_size)
        ##print(data.decode())
    else:
        print("cmd res receive done...",received_size)
        print(received_data.decode())
    # cmd_res=client.recv(1024)
    # print(cmd_res.decode())

client.close

5.作業:多使用者線上的輕量級ftp server實現
功能:1.使用者加密認證
2.允許多使用者同時登陸
3.每個使用者都有自己的家目錄,且只能訪問家目錄(許可權控制)
4.允許使用者在ftp server 上切換目錄
6.允許使用者檢視當前下目錄的檔案
7.支援上傳、下載,保證檔案一致性
8.檔案傳輸過程顯示進度條
未實現:磁碟配額,斷點續傳

github:https://github.com/yyyhhhrrr/ftpserver