美文网首页
粘包问题和解决方法

粘包问题和解决方法

作者: 住山洞的阿柔 | 来源:发表于2019-02-14 17:02 被阅读0次

什么是粘包问题

发送方发送的若干包数据到接收方时粘成一包,从接受缓冲区来看就是后一包数据的头紧接着前一包数据的尾。

粘包出现的原因

发送方等待到缓冲区满才将包发送出去

若连续几次发送数据都很小,tcp会根据优化算法把这些数据整合成一包后一次性发送,这样接收方就收到了粘包数据。

接收方不及时接受缓冲区的包,造成多个包接收

接收方会先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区读取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据进入缓冲区时就到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统中读取数据,这样便一次取了很多包。

解决方法--封包和解包

发送方在发送数据的包前,加入数据长度,将数据包的结构变成[dataLen|data]的结构再进行发送。而接收方通过解析这种结构,从而将多个数据包聚合形成的粘包分解成一个个独立的数据包。具体核心代码如下所示:
发送方封包:

const (
    DataLen = 4
)

//封装数据包
func Packet(message []byte) []byte {
    return append(IntToBytes(len(message)), message...)
}

接收方解包:

const (
    DataLen = 4
)

//解包
func Unpack(buffer []byte, readerChannel chan []byte) []byte {
    length := len(buffer)

    var i int
    for i = 0; i < length; i++ {
        if length < i + DataLen {
            break
        }
        //根据长度来获取数据
        messageLen := BytesToInt(buffer[i:i+DataLen])
        if length < i + DataLen + messageLen {
            break
        }
        data := buffer[i+DataLen:i+DataLen+messageLen]
        readerChannel <- data

        i += DataLen + messageLen - 1
    }

    if i == length {
        return make([]byte, 0)
    }
    return buffer[i:]
}

相关文章

网友评论

      本文标题:粘包问题和解决方法

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