week8-python之socket编程简单模拟ssh执行命令

python3模拟ssh服务

#############################################

用到模块有:socket,subprocess,struct,json,socketserver

实验环境:  linux服务器一台 ip:192.168.3.165   

                window pc一台   ip:192.168.3.10   

实现的功能:    1.支持多并发

                     2.支持常规的回显命令,如cat/ls/date/grep/echo/rm/touch等等

                     3.支持错误命令报错提示

                     4.支持大于2G以上的数据流传输

功能不足:不支持交互式命令操作,如:vi tailf等命令

bug:输入交互命令后客户端会卡住,需要强行结束重新连接

################################################

ssh_server.py代码,在python3环境下运行

#!/usr/bin/python3
#__utf8__
#__author:warren
import socket,subprocess,struct,json,socketserver
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
class MyTcphandler(socketserver.BaseRequestHandler):
        def handle(self):
                while True:
                        try:
                                cmd =self.request.recv(1024)
                                if not cmd: break
                                res = subprocess.Popen(cmd.decode("utf-8"), shell=True,
                                                       stdout=subprocess.PIPE,
                                                       stderr=subprocess.PIPE)
                                stdout = res.stdout.read()
                                stderr = res.stderr.read()

                                header_dic = {"total_size": len(stdout) + len(stderr), "md5": None}
                                header_json = json.dumps(header_dic).encode('utf-8')

                                res = struct.pack('i', len(header_json))
                                self.request.send(res)
                                self.request.send(header_json)

                                self.request.send(stdout)
                                self.request.send(stderr)
                        except Exception:
                                break
server_ssh=socketserver.ThreadingTCPServer(("0.0.0.0",8081),MyTcphandler)
#print("-----ssh start-----")
server_ssh.serve_forever()

 client.py代码,在python3环境运行,可跨平台

#__utf-8__
import socket,struct,json
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('192.168.3.165',8081))
while True:
    cmd=input('[localhost]# ').strip()
    if not cmd:continue
    #发命令
    client.send(cmd.encode('utf-8'))
    #先收报头的长度
    struct_res=client.recv(4)
    header_size=struct.unpack('i',struct_res)[0]
    #再收报头
    header_bytes=client.recv(header_size)
    head_json=header_bytes.decode('utf-8')
    head_dic=json.loads(head_json)
    total_size=head_dic['total_size']
    #再收命令的执行结果
    recv_size=0
    data=b''
    while recv_size < total_size:
        recv_data=client.recv(1024)
        recv_size+=len(recv_data)
        data+=recv_data
    #打印结果
    print(data.decode('utf-8'))
phone.close()

演示:

ssh_sever启动

[root@192-168-3-165 day8]# python3 ssh_server.py & 
[1] 10842
[root@192-168-3-165 day8]# ps aux |grep ssh_server.py |grep -v grep
root     10842  2.0  0.1 145876  7840 pts/1    S    21:55   0:00 python3 ssh_server.py

测试并发:客户端1                                                                                                                                         

 

测试并发:客户端2

相关详细知识点见下面博客地址:

http://www.cnblogs.com/linhaifeng/articles/6129246.html

单线程ssh服务

#!/usr/bin/python3.4
#__utf8__
import socket,subprocess,struct,json
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
server.bind(("0.0.0.0",8081))
server.listen(5)
print("#####server start...#####")
while True:
        conn,client_info=server.accept()
        print(conn,client_info)
        while True:
                try:
                        cmd=conn.recv(1024)
                        if not cmd:break
                        #conn.send(recv_data+".ok".encode("utf-8"))
                        res=subprocess.Popen(cmd.decode("utf-8"),shell=True,
                                             stdout=subprocess.PIPE,
                                             stderr=subprocess.PIPE)
                        stdout=res.stdout.read()
                        stderr=res.stderr.read()
                        # header = struct.pack("ii", len(stdout), len(stderr))

                        header_dic={"total_size":len(stdout)+len(stderr),"md5":None}
                        header_json=json.dumps(header_dic).encode('utf-8')

                        res=struct.pack('i',len(header_json))
                        conn.send(res)
                        conn.send(header_json)

                        conn.send(stdout)
                        conn.send(stderr)
                except Exception:
                        break
        conn.close()
server.close()
View Code

sockerserver实现多并发参考

import socketserver
class MyTcphandler(socketserver.BaseRequestHandler):
    def handle(self):
        while True: #通信循环
            data=self.request.recv(1024)
            self.request.send(data.upper())
if __name__ == '__main__':
    #取代链接循环
    server=socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyTcphandler)
    server.serve_forever()
View Code

 

posted @ 2017-08-20 21:21  warren1236  阅读(254)  评论(0)    收藏  举报