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