zoukankan      html  css  js  c++  java
  • TCP协议--黏包现象


    # 黏包现象
    # 本质: tcp协议是流式传输,信息与信息之间没有边界
    # 为什么会造成黏包
    # 合包机制: 在发送端,由于两条消息发送的间隔很短,且这两条消息本身很短, 在发送时被合并成一条消息
    # 在接收端,由于接受不及时导致两条先后到达的信息在接收端黏在了一起
    # 解决黏包问题 -- 自定义协议>> struct模块: 把2**31(2GB)以内的数字变成固定的4个字节
    # 简单的形式
    # 先发送数据的长度,再发送数据
    # 相对规范并复杂的形式
    # 先把所有想发送的数据信息放到字典里,
    # 再发送字典的长度
    # 再发送字典
    # 最后发送内容
    import os
    import json
    import struct
    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9001))
    
    filepath = input('请输入文件路径 :')
    filename = os.path.basename(filepath)              # os.path.basename 通过文件的路径,得到文件名
    filesize = os.path.getsize(filepath)               # 得到文件的大小
    dic = {'filename': filename, 'filesize': filesize} # 将文件名, 文件大小写进字典
    str_dic = json.dumps(dic)                          # 将字典序列化成字符串形式的字典
    bytes_dic = str_dic.encode('utf-8')                # 将字符串形式的字典 转成 字节
    len_dic = len(bytes_dic)                           # 得到 字节的长度
    bytes_len = struct.pack('i', len_dic)              # 用struck.pack() 将字节 转换成4位的字节
    sk.send(bytes_len)                                 # 发送得到的4位字节
    sk.send(bytes_dic)                                 # 发送字节
    with open(filepath, 'rb') as f:
        content = f.read()                             # 以rb模式 读取到文件中的内容
        sk.send(content)                               # 发送内容
    sk.close()
    
    # 先发送字典的长度
    # 再发字典 {'filename':xxxx,'filesize':xxxxx}
    # 再发文件内容
    解决黏包--client端
    
    
    import json
    import struct
    import socket
    
    sk = socket.socket()
    sk.bind(('127.0.0.1', 9001))
    sk.listen()
    
    conn, addr = sk.accept()
    num = conn.recv(4)                               # 接收4位字节
    num = struct.unpack('i', num)[0]                 # 读取4位字节, 获得字典长度
    str_dic = conn.recv(num).decode('utf-8')         # 读取字典长度, 得到字符串形式的字典
    dic = json.loads(str_dic)                        # 将字符串形式的字典反序列化, 得到字典
    with open(dic['filename'], 'wb') as f:
        content = conn.recv(dic['filesize'])         # 接收从客户端发来的, dic['filesize']这么大的文件内容
        f.write(content)
    
    conn.close()
    sk.close()
    解决黏包--server端
     
  • 相关阅读:
    2011年上半年软考信息系统项目管理师顺利通过了。
    技术工程师之歌
    大家都很注重能力的时候,我却在努力提高学历
    新的开发团队配合模式,适合小型团队
    研发部的四套马车
    mysql给root开启远程访问权限,修改root密码
    js客户端判断文件大小限制上传
    metro 微博api开发,post请求
    VS2010在C#头文件添加文件注释的方法
    android ListView 常见问题 之 高度问题
  • 原文地址:https://www.cnblogs.com/LL97155472/p/10682895.html
Copyright © 2011-2022 走看看