go语言下tcp粘包分包的简单处理

go在网络编程中真的很香

什么是粘包分包:

个人理解,
TCP的流式传输会因为网络状况而导致接收端每次收到的数据和发送端每次发送的数据略有差别 
e.g.  发送时为 {123} {456} 接受时为 {12} {3456}


方法1:使用websocket,无需处理
方法2:正常tcp流程下使用长度法:
利用time.Sleep(time.Nanosecond)来重现网络卡顿情况,复现粘包
服务端

func main(){
    listen , _ := net.Listen("tcp", "127.0.0.1:8888")
    fmt.Println("start listen")
    for {
        conn, err := listen.Accept()
        if err!=nil {
            continue
        }
        go process(conn)
    }
}
func process(conn net.Conn) {

    fmt.Printf("new conn %d", conn.RemoteAddr())
    // var buffer = make([]byte, 100)

    for {
        reader := bufio.NewReader(conn)
        peek, _ := reader.Peek(4)
        buffer := bytes.NewBuffer(peek)
        var length int32
        binary.Read(buffer, binary.BigEndian, &length)

        if int32(reader.Buffered()) < length+4 {
            continue
        }
        data := make([]byte, length+4)
        _, err := reader.Read(data)
        if err!=nil {
            continue
        }
        fmt.Println(string(data[4:]))

    }
}

客户端

func main() {

    conn, err:=     net.Dial("tcp", "127.0.0.1:8888")
    if err!=nil {
        fmt.Println(err)
        return
    }
    for i := 0; i < 100; i++{
        data, _ := Encode(time.Now().String())
        conn.Write(data)
        // time.Sleep(1*time.Second)

    }
}
func Encode(message string) ([]byte, error) {
    var length = int32(len(message))
    var pkg = new(bytes.Buffer)

    err := binary.Write(pkg, binary.BigEndian, length)
    if err!=nil {
        return nil, err
    }
    err = binary.Write(pkg, binary.BigEndian, []byte(message))
    if err!=nil {
        return nil, err
    }
    return pkg.Bytes(), nil

}

你可能感兴趣的:(golangsocket编程)