在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功能。
