老男孩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.檔案傳輸過程顯示進度條
未實現:磁碟配額,斷點續傳