zoukankan      html  css  js  c++  java
  • python-- socket 粘包、实现 ssh

    粘包

    只有tcp协议才会发送粘包,udp不会发生。发送端发送数据,接收端不知道应该如何去接收,造成的一种数据混乱的现象

    import subprocess
    r = subprocess.Popen('ls',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    # subprocess.Popen(cmd,shell=True,subprocess.stdout,subprocess.stderr)
    # cmd : 代表系统命令
    # shell = True   代表这条命令是 系统命令,告诉操作系统,将cmd当成系统命令去执行
    # stdout   是执行完系统命令之后,用于保存结果的一个管道
    # stderr   是执行完系统命令之后,用于保存错误结果的一个管道
    stdout = r.stdout.read().decode('gbk')
    stderr = r.stderr.read().decode('gbk')
    print('正确的返回结果:',stdout)
    print('错误的返回结果:',stderr)
    print('错误的返回结果:',stderr)

    客户端发送要执行命令

    服务器执行,执行完将结果返回给客户端

    客户端拿到结果呈现到用户眼前

    服务端

    import socket
    import subprocess
    
    sk = socket.socket()
    sk.bind(('127.0.0.1', 8080))
    sk.listen()
    
    conn, addr = sk.accept()
    while 1:
        cmd = conn.recv(1024).decode('utf-8')
        r = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout = r.stdout.read()
        stderr = r.stderr.read()
        if stderr:
            conn.send(stderr)
        else:
            conn.send(stdout)
    
    conn.close()
    sk.close()

    客户端

    import socket
    
    sk = socket.socket()
    sk.connect_ex(('127.0.0.1', 8080))
    while 1:
        cmd = input('请输入一个命令>>>')
        sk.send(cmd.encode('utf-8'))
        result = sk.recv(102)
        result = result.decode('gbk')
        print(result)
    
    sk.close()

    socket 实现 ssh

    a = ''
    print(len(a))  # 1
    print(len(a.encode()))  # 3  转换为bytes一个汉字三个字符

    客户端

    import socket
    
    client = socket.socket()
    client.connect(('localhost', 9999))
    while True:
        msg = input(">>:").strip()
        if len(msg) == 0:  # 输入的为空
            continue
        client.send(msg.encode("utf-8"))
        data = client.recv(1024)
        print("recv:", data.decode())
    client.close()

    服务端

    import socket, os
    
    server = socket.socket()
    server.bind(('localhost', 9999))
    server.listen()
    while True:
        conn, addr = server.accept()
        print('new conn', addr)
        while True:
            data = conn.recv(1024)
            if not data:
                print('客户端已断开')
                break
            print('执行指令:', data)
            cmd_res = os.popen(data.decode()).read()  # 执行输入的命令,decode转换为字符串
            if len(cmd_res) == 0:
                cmd_res = 'cmd has no out'
            conn.send(cmd_res.encode('utf-8'))  # 转为utf-8发过去

    当我们在客户端执行 ifconfig 命令时,第一次返回的不全(1024字节),在执行 ls 命令时,返回的是 ifconfig 剩下的命令(1024字节),如下

    >>:ifconfig
    recv: lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
        options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
        inet 127.0.0.1 netmask 0xff000000 
        inet6 ::1 prefixlen 128 
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 
        nd6 options=201<PERFORMNUD,DAD>
    gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
    stf0: flags=0<> mtu 1280
    ap1: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500
        options=400<CHANNEL_IO>
        ether b2:9c:4a:c4:34:e7 
        media: autoselect
        status: inactive
    en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        options=400<CHANNEL_IO>
        ether 90:9c:4a:c4:34:e7 
        inet6 fe80::18f2:9b2f:4496:675e%en0 prefixlen 64 secured scopeid 0x6 
        inet 192.168.31.110 netmask 0xffffff00 broadcast 192.168.31.255
        nd6 options=201<PERFORMNUD,DAD>
        media: autoselect
        status: active
    p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
        options=400<CHANNEL_IO>
        ether 02:9c:4a:c4:34:e7 
        media: autoselect
        status: inactive
    awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484
        opti
    >>:ls
    recv: ons=400<CHANNEL_IO>
        ether e2:3f:ba:ac:28:1d 
        inet6 fe80::e03f:baff:feac:281d%awdl0 prefixlen 64 scopeid 0x8 
        nd6 options=201<PERFORMNUD,DAD>
        media: autoselect
        status: active
    llw0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        options=400<CHANNEL_IO>
        ether e2:3f:ba:ac:28:1d 
        inet6 fe80::e03f:baff:feac:281d%llw0 prefixlen 64 scopeid 0x9 
        nd6 options=201<PERFORMNUD,DAD>
        media: autoselect
        status: active
    en2: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
        options=460<TSO4,TSO6,CHANNEL_IO>
        ether 1e:66:6c:14:0d:c4 
        media: autoselect <full-duplex>
        status: inactive
    en1: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
        options=460<TSO4,TSO6,CHANNEL_IO>
        ether 1e:66:6c:14:0d:c5 
        media: autoselect <full-duplex>
        status: inactive
    en3: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
        options=460<TSO4,TSO6,CHANNEL_IO>
        ether 1e:66:6c:14:0d:c1 
        media: autoselect <full-duplex>
        status: inactive
    en4: flags=8963<U

    全部接收

    先判断需要接收的数据,然后接收的和实际的对比,如果小于实际的,继续接收,否则,打印出接收的大小和命令

    客户端

    import socket
    
    client = socket.socket()
    client.connect(('localhost', 9999))
    while True:
        msg = input(">>:").strip()
        if len(msg) == 0:
            continue
        client.send(msg.encode("utf-8"))
        data_size = client.recv(1024)  # 接收命令的长度
        print('需要接收的数据大小:', data_size)
        client.send('开始发吧'.encode('utf-8'))  # 处理黏包
        reve_size = 0
        reve_data = b''
        while reve_size < int(data_size.decode()):  # data_size是byte类型
            data = client.recv(1024)
            reve_size += len(data)  # 每次收到的有可能小于1024,所以必须用len判断
            reve_data += data
        else:
            print('接收到的大小:', reve_size)
            print(reve_data.decode())
    client.close()

    服务端

    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()  # 执行输入的命令,decode转换为字符串
            print('数据的大小:', len(cmd_res))
            if len(cmd_res) == 0:
                cmd_res = 'cmd has no out'
            conn.send(str(len(cmd_res.encode())).encode('utf-8'))  # 数字不能encode。cmd_res.encode()将汉字转换成3个字节,不转发送的大小和接收的大小不一样
            conn.recv(1024)  # 处理黏包
            conn.send(cmd_res.encode('utf-8'))  # 转为 utf-8发过去
  • 相关阅读:
    ubuntu安装gnome桌面,ubuntu系统16升级到18
    重置root密码
    shell中tr的用法
    ubuntu14.04安装zabbix
    TTTTTTTTTTTTTT poj 1127 Jack Straws 线段相交+并查集
    TTTTTTTTTTTTT poj 3057 Evacuation 二分图匹配+bfs
    hdu 1208 Ignatius and the Princess III 划分数,dp
    Poj 3057 未AC http://poj.org/showsource?solution_id=15175171
    poj 3662 Telephone Lines dijkstra+二分搜索
    poj 3684 Physics Experiment 弹性碰撞
  • 原文地址:https://www.cnblogs.com/zouzou-busy/p/13771403.html
Copyright © 2011-2022 走看看