TCP粘包和拆包产生的原因
应用程序写入数据的字节大小大于套接字发送缓冲区的大小
进行MSS大小的TCP分段。MSS是最大报文段长度的缩写。MSS是TCP报文段中的数据字段的最大长度。数据字段加上TCP首部才等于整个的TCP报文段。所以MSS并不是TCP报文段的最大长度，而是：MSS=TCP报文段长度-TCP首部长度
以太网的payload大于MTU进行IP分片。MTU指：一种通信协议的某一层上面所能通过的最大数据包大小。如果IP层有一个数据包要传，而且数据的长度比链路层的MTU大，那么IP层就会进行分片，把数据包分成托干片，让每一片都不超过MTU。注意，IP分片可以发生在原始发送端主机上，也可以发生在中间路由器上。
TCP粘包和拆包的解决策略
消息定长。例如100字节。
在包尾部增加回车或者空格符等特殊字符进行分割，典型的如FTP协议
将消息分为消息头和消息尾。(len+data模式)
其它复杂的协议，如RTMP协议等。
废话不多说直接上代码
服务端
package network

import (
    "net"
    "bufio"
    "bytes"
    "encoding/binary"
)

type TcpClient struct {
    tag  string
    conn net.Conn
    r    *bufio.Reader
}

func NewTcpClint(conn net.Conn) *TcpClient {
    return &TcpClient{conn: conn, r: bufio.NewReader(conn)}
}

func (c *TcpClient) LocalAddr() net.Addr {
    return c.conn.LocalAddr()
}

func (c *TcpClient) RemoteAddr() net.Addr {
    return c.conn.RemoteAddr()
}

func (c *TcpClient) Close() error {
    return c.conn.Close()
}

func (c *TcpClient) Write(message []byte) (int, error) {
    // 读取消息的长度
    var length = int32(len(message))
    var pkg = new(bytes.Buffer)
    //写入消息头
    err := binary.Write(pkg, binary.BigEndian, length)
    if err != nil {
        return 0, err
    }
    //写入消息体
    err = binary.Write(pkg, binary.BigEndian, message)
    if err != nil {
        return 0, err
    }
    nn, err := c.conn.Write(pkg.Bytes())
    if err != nil {
        return 0, err
    }
    return nn, nil
}

func (c *TcpClient) Read() ([]byte, error) {
    // Peek 返回缓存的一个切片，该切片引用缓存中前 n 个字节的数据，
    // 该操作不会将数据读出，只是引用，引用的数据在下一次读取操作之
    // 前是有效的。如果切片长度小于 n，则返回一个错误信息说明原因。
    // 如果 n 大于缓存的总大小，则返回 ErrBufferFull。
    lengthByte, err := c.r.Peek(4)
    if err != nil {
        return nil, err
    }
    //创建 Buffer缓冲器
    lengthBuff := bytes.NewBuffer(lengthByte)
    var length int32
    // 通过Read接口可以将buf中得内容填充到data参数表示的数据结构中
    err = binary.Read(lengthBuff, binary.BigEndian, &length)
    if err != nil {
        return nil, err
    }
    // Buffered 返回缓存中未读取的数据的长度
    if int32(c.r.Buffered()) < length+4 {
        return nil, err
    }
    // 读取消息真正的内容
    pack := make([]byte, int(4+length))
    // Read 从 b 中读出数据到 p 中，返回读出的字节数和遇到的错误。
    // 如果缓存不为空，则只能读出缓存中的数据，不会从底层 io.Reader
    // 中提取数据，如果缓存为空，则：
    // 1、len(p) >= 缓存大小，则跳过缓存，直接从底层 io.Reader 中读
    // 出到 p 中。
    // 2、len(p) < 缓存大小，则先将数据从底层 io.Reader 中读取到缓存
    // 中，再从缓存读取到 p 中。
    _, err = c.r.Read(pack)
    if err != nil {
        return nil, err
    }
    return pack[4:], nil
}


package controller

import (
    "fmt"
    "test/tcp/network"
    "io"
    "net"
)

func ServerRun() {
    lister, err := net.Listen("tcp", "192.168.2.28:8888")
    fmt.Println("服务启动成功：192.168.2.28:8888")
    CheckErr(err)
    defer lister.Close()
    for {
        conn, err := lister.Accept()
        CheckErr(err)
        fmt.Println("用户接入")
        client := network.NewTcpClint(conn)
        go func() {
            defer client.Close()
            for {
                data, err := client.Read()
                if err == io.EOF {
                    fmt.Println("断开链接")
                    return
                }
                if err != nil {
                    continue
                }
                switchController(data, client)
            }
        }()
    }
}
func CheckErr(err error) {
    if err != nil {
        panic(err)
    }
}

func switchController(data []byte, c *network.TcpClient) {
    fmt.Println("读到的数据: " + string(data))
    switch string(data) {
    case "ping":
        c.Write([]byte("pong"))
        fmt.Println("发出的数据: pong")
        break
    }
}


客户端
package main

import (
    "testing"
    "net"
    "log"
    "fmt"
    "encoding/binary"
    "bytes"
    "time"
)

func Test(t *testing.T) {
    conn, err := net.Dial("tcp", "192.168.2.28:8888")
    if err != nil {
        log.Println("dial error:", err)
        return
    }
    defer conn.Close()
    for {
        data, _ := Encode("1")
        time.Sleep(time.Second * 4)
        _, err := conn.Write(data)
        fmt.Println(err)
    }
}
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
}