• TCP粘包


    TCP粘包问题

    TCP(transport control protocol,传输控制协议)是面向连接的,面向流的一种协议,没有固定的“报文”或者“报文边界”的概念。当发送端缓冲区的长度大于网卡的MTU时(MTU是Maximum Transmission Unit的缩写。意思是网络上传送的最大数据包。MTU的单位是字节。 大部分网络设备的MTU都是1500。如果本机的MTU比网关的MTU大,大的数据包就会被拆开来传送,这样会产生很多数据包碎片,增加丢包率,降低网络速度),tcp会将发送的数据拆成几个数据包发送出去。所以当网络出现堵塞或者发送频率过高的时候,就会出现粘包的情况。
    TCP为提高传输效率,发送方往往要收集到足够多的数据,将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出想要的数据包,在接收方看来,根本不知道该数据包的字节流从何处开始,在何处结束最终造成粘包。

    对于空消息:tcp是基于数据流的,于是收发的消息不能为空,这就需要在客户端和服务端都添加空消息的处理机制,防止程序卡住,而udp是基于数据报的,即便是你输入的是空内容(直接回车),也可以被发送,udp协议会帮你封装上消息头发送过去。
    可靠黏包的tcp协议:tcp的协议数据不会丢,没有收完包,下次接收,会继续上次接收,己端总是在收到ack时才会清除缓冲区内容。数据是可靠的,但是会粘包。

    UDP不会粘包

    UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。 不会使用块的合并优化算法,由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。
    对于空消息: udp是基于数据报的,即便是你输入的是空内容(直接回车),也可以被发送,udp协议会帮你封装上消息头发送过去。
    不可靠不黏包的udp协议:udp的recvfrom是阻塞的,一个recvfrom(r_size)必须对唯一一个sendinto(s_size),收完<=r_size个字节的数据就算完成,若是s_size>r_size(即发送数据包长度大于接收的数据的长度)多余的数据就丢失,这意味着udp根本不会粘包,但是会丢数据,不可靠。
    用UDP协议发送时,用sendto函数最大能发送数据的长度为:65535- IP头(20) – UDP头(8)=65507字节。用sendto函数发送数据时,如果发送数据长度大于该值,则函数会返回错误。(丢弃这个包,不进行发送)

  • 相关阅读:
    Envoy
    Redis 使用总结
    kafka(一)
    docker搭建kafka环境&&Golang生产和消费
    docker-composer +Grafana+Prometheus系统监控之Redis
    Docker基础命令
    connection pool exhausted
    golang 单元测试&&性能测试
    golang http 中间件
    golang 函数的特殊用法
  • 原文地址:https://www.cnblogs.com/caesar-id/p/12064583.html
Copyright © 2020-2023  润新知