粘包
- tcp粘包:
- tcp是流式协议:发送包的时候一次可能没有发完可能给了下一次 nagle算法导致客户端发送的粘包,本意是为了改善客户端网络
- nagle算法
该算法要求一个tcp连接上最多只能有一个未被确认的未完成的小分组,在该分组ack到达之前不能发送其他的小分组,tcp需要收集这些少量的分组,并在ack到来时以一个分组的方式发送出去;其中小分组的定义是小于MSS的任何分组; 该算法的优越之处在于它是自适应的,确认到达的越快,数据也就发哦送的越快;而在希望减少微小分组数目的低速广域网上,则会发送更少的分组;
- Nagle算法是以他的发明人John Nagle的名字命名的,它用于自动连接许多的小缓冲器消息;这一过程(称为nagling)通过减少必须发送包的个数来增加网络软件系统的效率。
if there is new data to send #有数据要发送
# 发送窗口缓冲区和队列数据 >=mss,队列数据(available data)为原有的队列数据加上新到来的数据
# 也就是说缓冲区数据超过mss大小,nagle算法尽可能发送足够大的数据包
if the window size >= MSS and available data is >= MSS
send complete MSS segment now # 立即发送
else
if there is unconfirmed data still in the pipe # 前一次发送的包没有收到ack
# 将该包数据放入队列中,直到收到一个ack再发送缓冲区数据
enqueue data in the buffer until an acknowledge is received
else
send data immediately # 立即发送
end if
end if
end if
https://baike.baidu.com/item/Nagle%E7%AE%97%E6%B3%95
粘包演示
服务端代码
package main
import (
"fmt"
"net"
)
func main() {
// 本地端口启动服务
listener, err := net.Listen("tcp", "localhost:20000")
if err != nil {
fmt.Println("服务器启动失败....", err)
return
}
fmt.Println("监听成功...")
// 等待连接
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("连接建立失败...", err)
break
}
fmt.Println("连接成功...")
go Process(conn)
}
// 通信
}
func Process(conn net.Conn) {
var temp [128]byte