zoukankan      html  css  js  c++  java
  • 解决tcp协议的粘包问题

    一、远程执行命令的程序

    服务端:

    from socket import *
    import subprocess

    server=socket(AF_INET,SOCK_STREAM)
    server.bind(('127.0.0.1',8080))
    server.listen(5)

    while True:
    conn,client_addr=server.accept() #(连接对象,客户端的ip和端口)
    print(client_addr)
    while True:
    try:
    cmd=conn.recv(1024)
    if len(cmd)==0:break

    obj=subprocess.Popen(cmd.decode('utf-8'),
    shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE

    )
    stdout=obj.stdout.read()
    stderr=obj.stderr.read()


    conn.send(stdout+stderr)

    except ConnectionResetError:
    break

    conn.close()
    server.close()


    客户端:
    from socket import *

    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8080))
    # print(client)

    while True:
    cmd=input('>>>: ').strip()
    if not cmd:continue
    client.send(cmd.encode('utf-8'))
    res=client.recv(1024)
    print(res.decode('gbk'))

    client.close()


    二、解决tcp协议的粘包问题

    补充struct模块:
        1、把整形数字转成bytes类型
        2、转成的bytes固定长度


    服务端:

    from socket import *
    import subprocess
    import struct
    import json

    server=socket(AF_INET,SOCK_STREAM)
    server.bind(('127.0.0.1',8080))
    server.listen(5)

    while True:
    conn,client_addr=server.accept()
    print('新的客户端',client_addr)

    while True:
    try:
    cmd=conn.recv(1024) #cmd=b'dir'
    if len(cmd) == 0:break

    # 运行系统命令
    obj=subprocess.Popen(cmd.decode('utf-8'),
    shell=True,
    stderr=subprocess.PIPE,
    stdout=subprocess.PIPE
    )

    stdout=obj.stdout.read()
    stderr=obj.stderr.read()

    #先制作报头
    header_dic={
    'filename':'a.txt',
    'total_size':len(stdout) + len(stderr),
    'hash':'xasf123213123'
    }
    header_json=json.dumps(header_dic)
    header_bytes=header_json.encode('utf-8')

    #1、先把报头的长度len(header_bytes)打包成4个bytes,然后发送
    conn.send(struct.pack('i',len(header_bytes)))
    #2、发送报头
    conn.send(header_bytes)
    #3、再发送真实的数据
    conn.send(stdout)
    conn.send(stderr)
    except ConnectionResetError:
    break

    conn.close()

    客户端:

    from socket import *
    import struct
    import json

    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8080))

    while True:
    cmd=input('>>: ').strip()
    if len(cmd) == 0:continue
    client.send(cmd.encode('utf-8'))

    #1、先收4个字节,该4个字节中包含报头的长度
    header_len=struct.unpack('i',client.recv(4))[0]

    #2、再接收报头
    header_bytes=client.recv(header_len)

    #从报头中解析出想要的内容
    header_json=header_bytes.decode('utf-8')
    header_dic=json.loads(header_json)
    print(header_dic)
    total_size=header_dic['total_size']


    #3、再收真实的数据
    recv_size=0
    res=b''
    while recv_size < total_size :
    data=client.recv(1024)
    res+=data
    recv_size+=len(data)

    print(res.decode('gbk'))
  • 相关阅读:
    MFC加载皮肤 转自:http://www.cctry.com/thread-4032-1-1.html
    内存不能为read修复方法:(转自:网上(忘记了))
    Kalendar server Beijing Tiandiyuandian Technology Limited 果然是木马
    牛人面经
    安装graphlab伤透了心,终于搞定了
    哨兵模式下,master选举关键点
    redis哨兵模式,数据尽量少的丢失
    使用@import导入实现了ImportBeanDefinitionRegistrar接口的类,不能被注册为bean
    redis使用rdb恢复数据
    spring boot动态数据源方案
  • 原文地址:https://www.cnblogs.com/kingyanan/p/9296143.html
Copyright © 2011-2022 走看看