python 解决粘包现象(struct模块)

一. struct模块

   该模块可以把一个类型,转换为固定长度的bytes

import struct
lst  = [1,2,4,3,5,]
lst1  = [1,2,4,3,5,7,8,9,]
a = struct.pack(‘i‘,len(lst))#将列表的长度转化为固定的4字节
b = struct.pack(‘i‘,len(lst1))
print(a,len(a))
print(b,len(b))

  符号对应的类型以及转换之后的长度表 :

  struct模块实现大文件传输 :

#server端
import socket
import struct
import json
import os

sk = socket.socket()
sk.bind((‘127.0.0.1‘,8989))
sk.listen()
conn,addr = sk.accept()

len_dic = struct.unpack(‘i‘,conn.recv(4))[0]#unpack解包接受的是元组类型,索引为0是字典的长度
str_dic = conn.recv(len_dic).decode(‘utf-8‘)#根据字典的长度将字典接收为字符串类型
dic = json.loads(str_dic)#将字符串类型的字典转换为字典(dict)
if dic[‘opt‘] == ‘upload‘:
    up_load = ‘D:\a\b\c\\‘ + os.path.basename(dic[‘filename‘])#路径拼接
    # up_load = os.path.join(‘D:\a\b\c\\‘,os.path.basename(dic[‘filename‘]))
    while dic[‘filesize‘] >0:
        read_size = conn.recv(2048)
        with open(os.path.abspath(up_load),mode=‘ab‘) as f1:
            f1.write(read_size)
            dic[‘filesize‘] -= len(read_size)

if dic[‘opt‘] == ‘download‘:
    down_load = ‘D:\a\b\c‘
    conn.send(json.dumps(os.listdir(down_load)).encode(‘utf-8‘))
    while 1:
        s = conn.recv(2048).decode(‘utf-8‘)
        file = os.path.abspath(down_load+‘/‘+s)
        print(file)
        if os.path.isdir(file):
            dic1 = {‘tybe‘:‘dir‘}
            len_dic1 = struct.pack(‘i‘,len(json.dumps(dic1)))
            conn.send(len_dic1 + json.dumps(dic1).encode(‘utf-8‘))
            conn.send(json.dumps(os.listdir(file)).encode(‘utf-8‘))
            down_load = os.path.abspath(file)
            continue
        elif os.path.isfile(file):
            dic2 = {‘tybe‘:‘fil‘,‘down_size‘:os.path.getsize(file)}
            len_dic2 = struct.pack(‘i‘,len(json.dumps(dic2)))
            conn.send(len_dic2 + json.dumps(dic2).encode(‘utf-8‘))
            with open(file,mode=‘rb‘) as f:
                down_size = os.path.getsize(file)
                while down_size:
                    a = f.read(2048)
                    print(a)###########
                    conn.send(a)
                    down_size -= len(a)
                break
#client端
import socket
import struct
import os
import json

sk = socket.socket()
sk.connect((‘127.0.0.1‘,8989))
def upload():
    dic = {‘opt‘:‘upload‘,‘filename‘:None,‘filesize‘:None}
    file = input(‘请输入一个想要上传的绝对路径: ‘)
    dic[‘filename‘] = file
    dic[‘filesize‘] = os.path.getsize(file)
    str_dic = json.dumps(dic)
    len_dic = struct.pack(‘i‘,len(str_dic))#自动将字典的长度转换为4个bytes类型的长度
    sk.send(len_dic + str_dic.encode(‘utf-8‘))

    with open(dic[‘filename‘],mode=‘rb‘) as f:
        while dic[‘filesize‘] > 0:
            read_size = f.read(2048)
            sk.send(read_size)
            dic[‘filesize‘] -= len(read_size)

def download():
    dic = {‘opt‘:‘download‘,‘filename‘:None,‘filesize‘:None}
    sk.send(struct.pack(‘i‘,len(json.dumps(dic)))+json.dumps(dic).encode(‘utf-8‘))
    while 1:
        lst = json.loads(sk.recv(2048).decode(‘utf-8‘))
        for k, v in enumerate(lst, 1):
            print(k, v)
        file = input(‘请根据序号输入想要下载的文件: ‘)
        sk.send(lst[int(file) - 1].encode(‘utf-8‘))
        len_dic = struct.unpack(‘i‘,sk.recv(4))[0]
        str_dic = sk.recv(len_dic).decode(‘utf-8‘)
        if json.loads(str_dic)[‘tybe‘] == ‘dir‘:
            continue
        elif json.loads(str_dic)[‘tybe‘] == ‘fil‘:
            down_file = ‘D:\a\b\c\\‘+lst[int(file) - 1]
            while json.loads(str_dic)[‘down_size‘]:
                with open(down_file,mode=‘ab‘) as f:
                    down_ = sk.recv(2048)
                    f.write(down_)
                json.loads(str_dic)[‘down_size‘] -= len(down_)

if __name__ ==‘__main__‘:
    lst = [‘上传‘, ‘下载‘]
    def mai():
        for k,v in enumerate(lst,1):
            print(k,v)
        c = input(‘请按序号输入操作: ‘)
        if c == ‘1‘:
            upload()
        if c == ‘2‘:
            download()
        else:
            print(‘输入错误!‘)
    mai()

原文地址:https://www.cnblogs.com/dong-/p/9494734.html

时间: 2024-11-06 09:52:52

python 解决粘包现象(struct模块)的相关文章

网络编程基础粘包现象

粘包 tcp是流式传输,字节流,数据与数据之间是没有边界的 流式传输优点: 不限定长度 可靠传输 缺点: 慢 和一个人的通信连接conn会一直占用我们的通信资源 udp协议,面向数据包的传输 数据包优点 快 由于不需要建立连接,所以谁发的消息我都能接受到 缺点 不能传输过长的数据 不可靠 粘包现象 由于流式传输的特点,产生了数据连续发送的粘包现象. 在一个conn建立起来的连接上传输的多条数据是没有边界的 数据的发送和接收实际上不是在执行send/recv的时候就立刻被发送和接收,而是需要经过操

Python网络编程03/ low版解决粘包问题

目录 Python网络编程03/ low版解决粘包问题 1.操作系统的缓存区 2.基于TCP协议的socket循环通信 2.1 服务端(server) 2.2客户端(client) 3.基于TCP协议的socket链接+循环 通信 3.1服务端(server) 3.2 客户端(client) 4.基于TCP协议的socket应用实例:执行远程命令 4.1服务端(server) 4.2客户端(client) 5.粘包现象 5.1服务端(server) 5.2客户端(client) 5.3展示收发问

python--subprocess,粘包现象与解决办法,缓冲区

一. subprocess 的简单用法 import subprocess sub_obj = subprocess.Popen( 'dir', #系统指令 shell=True, #固定方法 stdout=subprocess.PIPE, #标准输出 PIPE 管道,保存着指令的执行结果 stderr=subprocess.PIPE #标准错误输出 ) # dir 当前操作系统(Windows)的命令,会执行stdout print('正确输出',sub_obj.stdout.read().d

粘包现象(存在于tcp中)

多个包 多个命令的结果 粘到一起了 因为recv(1024)1024限制了导致的结果 所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的. 参考:http://www.cnblogs.com/linhaifeng/articles/6129246.html 粘包底层原理分析: 1.运行一个软件和硬盘.内存.cpu这三个硬件有关 2.启动程序:硬盘程序加载到内存启动一个软件就占一个内存空间 操作系统本身有一个内存空间 操作系统所占得到内存空间和软件的内存空间

Python网络编程04/recv原理/高大上版解决粘包方式

目录 Python网络编程04/recv原理/高大上版解决粘包方式 1.昨日内容回顾 2.recv工作原理 3.高大上版解决粘包方式(自定制报头) 3.1 解决思路: 3.2 服务端 3.3客户端 4.基于UDP协议的socket通信 4.1服务端 4.2客户端 Python网络编程04/recv原理/高大上版解决粘包方式 1.昨日内容回顾 1. 通信循环 2. 链接通信循环 3. 远程执行命令: subprocess.Popen() # bytes: 网络传输, 文件存储时. 4. 粘包现象

10.python网络编程(解决粘包问题 part 2)

一.什么时候会产生粘包现象. 只有在使用tcp协议的情况下才会产生粘包现象!udp协议永远不会! 发送端可以1k1k的把数据发送出去,接收端,可以2k2k的的去接收数据,一次可能会接收3k,也有可能1次接收6k. TCP协议是面向流的协议,这也是容易出现粘包问题的原因.而UDP是面向消息的协议,每个UDP段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据,这一点和TCP是很不同的.怎样定义消息呢?可以认为对方一次性write/send的数据为一个消息,需要明白的是当对方

python学习_day30_基于tcp协议的粘包现象

1.基于远程执行命令的程序 需用到subprocess模块 服务端: #1.执行客户端发送的指令 import socket import subprocess phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bind(('127.0.0.1',8090)) phone.listen(5) while True: conn,addr=phone.accept() print('IP:%s PORT:%s' %(addr[0

python3 tcp的粘包现象和解决办法

服务器端 import socket sk = socket.socket() sk.bind(("127.0.0.1", 6666)) sk.listen() conn, address = sk.accept() def my_send(msg): bs = msg.encode("utf-8") len_str = format(len(bs), "04d") # 定长4位 conn.send(len_str.encode("ut

粘包现象

一.基于udp的套接字 udp是无链接的,先启动哪一端都不会报错 udp服务端: ss = socket() #创建一个服务器的套接字 ss.bind() #绑定服务器套接字 while True : #服务器无限循环 cs = ss.recvfrom()/ss.sendto() # 对话(接收与发送) ss.close() # 关闭服务器套接字 udp客户端: cs = socket() # 创建客户套接字 while True : # 通讯循环 cs.sendto()/cs.recvfrom