在python socket知識點中已經對socket進行了初步的了解,那現在就使用這些知識來實現一個簡單的ssh(Secure Shell)功能。
首先同樣是建立兩個端(服務器端和客戶端)
需求是:服務器端需要對客戶端發送過來的命令進行相應,並將響應內容返回給客戶端。
看似很簡單的需求,但是如何響應命令行?python官方建議buffer的大小不宜超過8k(8192byte),如果返回的數據大於了buffer如何讓客戶端接收完全?信號傳輸過程只能通過byte類型,而命令執行過程又需要使用到str,所以在程序中的類型轉換也至關重要。
服務器端:
while True:#多用戶連接 conn,addr = server.accept()#等活動開始,accept會返回兩個值,conn就是客戶端對應在服務器端的連接實例,addr就是客戶端鏈接過來的地址,產生阻塞 while True: print("listened") data = conn.recv(1024)#不超過8192,默認是阻塞的,當客戶端一斷開,會陷入一個死循環,因為客戶端會不斷的發空"" if not data: print("客戶端已斷開") break print('執行指令:',data) cmd_os = os.popen(data.decode()).read()#地址為當前所在目錄 cmd_byte = cmd_os.encode('utf-8') print('發送長度',len(cmd_byte)) if len(cmd_os) == 0:#客戶端已斷開 cmd_os = "Invalid Command" conn.send(str(len(cmd_byte)).encode('utf-8'))#發送第一個:回傳長度,判斷是否需要循環接收數據 conn.send(cmd_os.encode('utf-8'))#發送第二個:回傳數據,將結果返回給客戶端 print('send done....') server.close()
客戶端:
import socket client = socket.socket()#聲明socket的類型,同時生成socket的連接對象 client.connect(('localhost',6969) )#連接的端口號和端口名 while True: msg = input('>>:'.strip()) if len(msg) == 0: continue client.send(msg.encode('utf-8'))#需要發送的數據 print('send',msg) data_size = 0#定義收到的數據大小 recv_data = b''#初始化接收數據 res_size = client.recv(1024)#接收從服務器端回傳的數據大小 print('the length of res:',res_size.decode()) while data_size < int(res_size.decode()):#如果數據大小小於回傳的數據大小便循環接收 recv_data+= client.recv(1024)#默認最大接收的字節數 data_size = len(recv_data)#進行下次循環判定 else: print('the length of recv:',len(recv_data)) print(recv_data.decode())#打印接收到的數據 client.close()#關閉客戶端
由以上程序,便可實現完整的命令傳遞以及結果回傳。實現簡單的ssh功能。