• CSIC_716_20191205【TCP-解决粘包问题、UDP模板】


    ------------------------------------------------------------------------------------------------------------------------------------

     客户端代码模板:(以ssh为例)

    # _*_ coding: gbk _*_
    # @Author: Wonder
    
    import socket
    import json
    import struct
    
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('172.16.10.19', 9527))
    
    while True:
        try:
            cmd = input('>>>请输入指令').strip()
            if not cmd:
                continue
            if cmd == 'q':
                break
            cmd = cmd.encode('utf-8')
            dict_context = {
                'data_size': len(cmd)  # 二进制的长度
            }
            client_bytes = json.dumps(dict_context).encode('utf-8')  # dict----->json------->binary 报头
            head = struct.pack('i', len(client_bytes))  # struct 将报头长度巧妙的转为4 bit
    
            # 以下为一波socket三连发送操作。
            client.send(head)  # 发报头长度,
    
            client.send(client_bytes)  # 发报头,里面有实际数据的长度
    
            client.send(cmd)  # 传数据
    
            bin_head = client.recv(4)  # 接收来自server的报头信息
            json_head_len = struct.unpack('i', bin_head)[0]  # unpack  获取报文头长度
            head_json = client.recv(json_head_len).decode()  # 解码 获得 json格式的 报头字典
            dic_head = json.loads(head_json)  # 反序列化,得到 data的长度所在的字典
            size = dic_head.get('data_size')  # 取到data的真实长度值
            length = 0
            bin_toatal = b''
    
            while length < size:
                bin_content = client.recv(500)
                bin_toatal += bin_content
                length += len(bin_content)      # 此处要累加bin_content的长度
                print('当前下载进度',size , length , length / size)
            print('当前下载进度---------------->', length / size)
    
            print(bin_toatal.decode('gbk'))
    except Exception as e: print(e) break client.close()

      

     服务端模板:

    # _*_ coding: gbk _*_
    # @Author: Wonder
    import socket
    import subprocess
    import json
    import struct
    
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('172.16.10.180', 9527))
    server.listen(3)
    while True:
        conn, addr = server.accept()
        while True:
            try:
    
                bin_head = conn.recv(4)  # 获取4位长度的报文头
                json_head = struct.unpack('i', bin_head)[0]  # 获得报头长度--->int
    
                bin_head = conn.recv(json_head).decode('utf-8')  # 获取报头信息 ------>binary----->JSON
                dic_head = json.loads(bin_head)  # 反序列化得到字典
                size = dic_head.get('data_size')  # 字典取值得到数据长度
    
                length = 0
                bin_toatal = b''
                while length < size:  # if 循环接收,直到长度和报头中的长度一致
                    bin_content = conn.recv(50)
                    bin_toatal += bin_content
                    length += len(bin_toatal)
    
                cmd = bin_toatal.decode('utf-8')
    
                subprocess_obj = subprocess.Popen(cmd, shell=True,
                                                  stdout=subprocess.PIPE,
                                                  stderr=subprocess.PIPE)
                stdout = subprocess_obj.stdout.read()  # binary
                stderr = subprocess_obj.stderr.read()
    
                back_data_len = len(stderr) + len(stdout)
                print(back_data_len)
    
                server_dict = {
                    'data_size': back_data_len  # 务必代表二进制的长度
                }
                back_json = json.dumps(server_dict).encode('utf-8')  # 序列化成  json字典  ------->json----->binary
                server_head = struct.pack('i', len(back_json))  # 转成4位长度的二进制, 表示报头长度
                conn.send(server_head)  # 发报头长度
                conn.send(back_json)  # 发报头
                conn.send(stdout)  # 发数据
                conn.send(stderr)
    
            except Exception as e:
                print(e)
                break
        conn.close()
    server.close()
    

     

     

     UDP的初级使用

    UDP服务端(即时通讯,你一句我一句)

    # _*_ coding: gbk _*_
    # @Author: Wonder
    import socket
    
    # 指定是 数据报,type= 一定要写,不然报错
    sk = socket.socket(type=socket.SOCK_DGRAM)
    sk.bind(
        ('127.0.0.1', 9527)
    )
    
    while True:
        data, addr = sk.recvfrom(1024)
        print(data.decode('utf-8'))
        sk.sendto('永不在线'.encode('UTF-8'), addr)
    

    客户端要绑定, 接收是recvfrom ,接收的是data和addr ,发送是sendto,发送的是data和目标addr

    UDP客户端

    # _*_ coding: gbk _*_
    # @Author: Wonder
    import socket
    
    sk = socket.socket(type=socket.SOCK_DGRAM)
    addr = ('127.0.0.1', 9527)
    while True:
        msg = input('>>>输入内容')
        if msg == 'q':
            break
        sk.sendto(msg.encode('utf-8'), addr)
        data, back = sk.recvfrom(1024)
        print(data.decode('utf-8'))
    

      

  • 相关阅读:
    不怕上不了 Android developers
    不花钱的可靠性设计
    linux2.6 内核特性配置
    Linux动态库的编译与使用 转载
    多线程使用互斥锁的C范例
    TSLIB 分析
    Notepad++中文版下载 以及HEX显示
    C程序实现在lcd 上全屏写 blue 色 及获取fb信息
    pthread_cond_wait的spurious wakeup问题
    查看linux内存条数的命令与清理内存使用
  • 原文地址:https://www.cnblogs.com/csic716/p/11991451.html
Copyright © 2020-2023  润新知