美文网首页
day32流式协议

day32流式协议

作者: 荭鲤鱼与緑鲤鱼与驴 | 来源:发表于2020-08-17 09:34 被阅读0次

流式协议

流式协议会产生粘包问题

发送端可以是1k1k的发送数据,而接收端的应用程序可以2k2k的提走数据,当然也有可能一次提走3k或6k数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体,或者说是一个流(stream),一条消息有多个字节对应程序是不可见的,因此TCP协议是面向流的协议,这也是容易出现粘包问题的原因

所谓粘包问题主要是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的.

TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一个TCP段.若连续几次需要send的数据都很少,通常TCP会根据优化算法把这些数据合成一个TCP段后一次发送出去,这样接收方就收到了粘包数据

两种情况会发生粘包

发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据很小,会合到一起,产生粘包)

接收方不即使接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)

解决方法:自定义应用层协议

为字节流加上自定义固定长度报头,包头中包含字节流长度,然后一次send到对端,对端在接收时,先从缓存中取出定长的报头,然后再取真是数据

struct模块:该模块可以把一个类型,如数字,转成固定长度的bytes

struct.pack('i',1111111111)

struct.error:'i' format requires -2147483648 <= number <= 2147483647 # 这个是范围 #

发送时

先发送报头长度

再编码报头内容然后发送

最后发送真实内容

接收时

先收报头长度,用struct提取出来

根据取出的长度收取报头内容,然后解码,反序列化

从反序列化的结果中取出待取数据的详细信息,然后去取真实的数据内容

服务端

import subprocess

import struct

from socket import *

server = socket(AF_INET, SOCK_STREAM)

server.bind(('127.0.0.1', 8080))

server.listen(5)

while True:

    conn, client_addr = server.accept()

    print(conn)

    print(client_addr)

    while True:

        try:

            cmd = conn.recv(1024)

            obj = subprocess.Popen(cmd.decode('utf-8'),

                                  shell=True,

                                  stdout=subprocess.PIPE,

                                  stderr=subprocess.PIPE,

                                  )

            stdout = obj.stdout.read()

            stderr = obj.stdout.read()

            total_size = len(stdout) + len(stderr)

            # 先发送数据的长度

            conn.send(struct.pack('i',total_size))

            # 发送真正的数据

            conn.send(stdout)

            conn.send(stderr)

        except Exception:

            break

    conn.close()

客户端

import struct

from socket import *

client = socket(AF_INET, SOCK_STREAM)

client.connect(('127.0.0.1', 8082))

while True:

    cmd = input(">>: ").strip()

    if len(cmd) == 0:

        continue

    client.send(cmd.encode('utf-8'))

    # 先收数据的长度

    n = 0

    header = b''

    while n < 4:

        data = client.recv(1)

        header += data

        n += len(data)

    total_size = struct.unpack('i', header)[0]

    # 收真正的数据

    recv_size = 0

    res = b''

    while recv_size < total_size:

        data = client.recv(1024)

        res += data

        recv_size += len(data)

    print(res.decode('gbk'))

client.close()

相关文章

  • day32流式协议

    流式协议 流式协议会产生粘包问题 发送端可以是1k1k的发送数据,而接收端的应用程序可以2k2k的提走数据,当然也...

  • www

    TCP 是流式协议,何为流式协议?其实就像河流一样,精确计算到底有多少立方水,不可测量。 比如,你打一个电话之前,...

  • UICollectionView 最简单的流式布局

    UICollectionViewFlowLayout 是系统提供的流式布局 2 .实现这俩个协议 UICollec...

  • 【笔记】谢希仁—计网五版:chapter eight 因特网上的

    本章对因特网提供音频/视频服务进行概述,然后介绍流式音频/视频中的媒体服务器和实时流式协议RTSP,并以IP电话为...

  • 流式套接字学习笔记

    本文首发于Amber's Blog-流式套接字学习笔记 流式套接字依托TCP协议提供面向连接的、可靠的数据传输服务...

  • day32-粘包问题和报头的定制

    粘包问题 TCP协议作为流式协议,只有TCP协议存在粘包问题。 发送端可以是一K一K地发送数据,而接收端的应用程序...

  • 10.12学习总结

    今天MFC课程完全结束了。讲了网络通信中的TCP协议通信,包括流式套接字,服务器与客户机进行连接,发送与接受流式数...

  • 深入了解Netty【八】TCP拆包、粘包和解决方案

    1、TCP协议传输过程 TCP协议是面向流的协议,是流式的,没有业务上的分段,只会根据当前套接字缓冲区的情况进行拆...

  • 直播架构分析

    推荐:https://www.imooc.com/learn/959 TCP:可靠地,流式传输协议UDP:不可靠,...

  • 初见Linux-socket

    什么叫网络编程? 就是使用网络协议,进行网络通信。数据报->UDP 流式套接字-> TCP 原始套...

网友评论

      本文标题:day32流式协议

      本文链接:https://www.haomeiwen.com/subject/uzpfjktx.html