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}