zoukankan      html  css  js  c++  java
  • 粘包的产生原理 以及如何解决粘包问题

    内容回顾:
    如何与另外一台电脑连接:
    ping 对方的ip地址
    如何参电脑的ip配置
    cmd-->ipconfig

    内容概览:
    粘包问题
    粘包产生原理
    如何解决粘包问题


    粘包的产生:

    #server
    import  socket
    sk = socket.socket()
    ip_port = ('127.0.0.1',8989)
    sk.bind(ip_port)
    sk.listen()
    conn,addr = sk.accept()
    conn.send(b'hello,')
    conn.send(b'world')
    conn.close()
    sk.close()
    

      



    #client
    import socket
    sk = socket.socket()
    ip_port = ('127.0.0.1',8989)
    sk.connect(ip_port)
    ret1 = sk.recv(2)
    print(ret1)
    ret2 = sk.recv(1024)
    print(ret2)
    sk.close()
    

      



    #client端收到的结果
    b'he'
    b'llo,'
    

      



    什么是粘包?
    数据之间没有分界线,导致两个数据粘合在一起,被接收端接收的现象,就叫做粘包
    -------------插入图片————————
    粘包产生的原因:
    发送端将两个挨得很近的数据,发送出去,在本地的缓存区粘合在一起,传输给对方,
    对方接收到数据之后,由于数据没有界限,于是将两个粘合在一起的数据一起接收。
    合包现象:
    数据很短
    时间间隔很近

    拆包现象:
    大数据在传输的过程中会发生拆包现象
    不会一次性的将数据全部发送给对方
    对方接收的时候很可能没有办法一次性接收所有的信息
    对方一次没有接收完的信息,会与后面的信息粘在一起

    粘包现象只会发生在TCP协议
    TCP的协议是流式传输
    每一条信息与信息之间是没有界限的

    UDP协议中是不会发生粘包的
    UDP协议适合短数据的发送
    不建议发送过程的信息
    数据越长,传输逇过程中,会越容易丢失

    解决粘包问题的初探:
    能否在发送信息的时候把信息的长度一起发送,接收方根据长度来截取信息。

    #server
    import  socket
    sk = socket.socket()
    ip_port = ('127.0.0.1',8989)
    sk.bind(ip_port)
    sk.listen()
    
    conn,addr = sk.accept()
    conn.send(b'0011hello,zhuge')
    conn.send(b'0005world')
    
    conn.close()
    sk.close()
    

      



    #client
    import socket
    sk = socket.socket()
    ip_port = ('127.0.0.1',8989)
    sk.connect(ip_port)
    
    ret1 = sk.recv(4)
    len1 = int(ret1.decode('utf-8'))
    ret2 = sk.recv(len1)
    print(ret2.decode('utf-8'))
    
    ret3 = sk.recv(4)
    len2 = int(ret3.decode('utf-8'))
    ret4 = sk.recv(len2)
    print(ret4.decode('utf-8'))
    
    sk.close()
    

      



    #client显示结果:
    hello,zhuge
    world
    

      



    总结一下:
    上面的办法虽然解决了问题但是存在漏洞,要是长度超过9999就不好使了。
    有没有一种算法,输入任意长的数字,得到的是一个四位数,
    这个四位数,被接收之后,又可以根据算法反推出这个任意长的数是多少,那么问题就解决了。

    struck模块

    #server端


    conn,addr = sk.accept()
    while True:
        s = input('>>>').encode('utf-8')
        pack_num = struct.pack('i',len(s))#s的长度转化成一个4位数
        conn.send(pack_num)
        conn.send(s)
    
    conn.close()
    sk.close()
    

      



    #client端
    import socket
    import struct
    sk = socket.socket()
    ip_port = ('127.0.0.1',8989)
    sk.connect(ip_port)
    
    while True:
        pack_num = sk.recv(4)
        num = struct.unpack('i',pack_num)[0]#这里有个坑,得到的是元组,(10,)
        ret = sk.recv(num)
        print(ret.decode('utf-8'))
    
    sk.close()
    

      




  • 相关阅读:
    各类 HTTP 返回状态代码详解
    ANDROID内存优化——大汇总(转)
    Process Stats:了解你的APP如何使用内存(转)
    Android开发之AlarmManager详解
    转 16 jmeter中的监听器以及测试结果分析
    转 15 jmeter分布式性能测试
    转 14 jmeter性能测试实战--数据库MySQL
    转 12 jmeter性能测试实战--web程序
    转 11 jmeter之图形监控扩展
    转 10 jmeter之动态关联
  • 原文地址:https://www.cnblogs.com/cavalier-chen/p/9649078.html
Copyright © 2011-2022 走看看