网站换皮肤了
golang-tcp网络半包粘包解决方案
时间:2018-05-14 12:45 浏览:132

摘要

none
package main
import (
    "bufio"
    "bytes"
    "encoding/binary"
    "fmt"
    "io"
    "log"
    "os"
    "strconv"
    "sync"
    "time"
)
var m *sync.Mutex = new(sync.Mutex)
type Package struct {
    Version        [2]byte // 协议版本
    Length         int16   // 数据部分长度
    Timestamp      int64   // 时间戳
    HostnameLength int16   // 主机名长度
    Hostname       []byte  // 主机名
    Body           []byte  // 消息主体
}
func (p *Package) Pack(writer io.Writer) error {
    var err error
    err = binary.Write(writer, binary.BigEndian, &p.Version)
    err = binary.Write(writer, binary.BigEndian, &p.Length)
    err = binary.Write(writer, binary.BigEndian, &p.Timestamp)
    err = binary.Write(writer, binary.BigEndian, &p.HostnameLength)
    err = binary.Write(writer, binary.BigEndian, &p.Hostname)
    err = binary.Write(writer, binary.BigEndian, &p.Body)
    return err
}
func New(body string) (pack *Package) {
    hostname, err := os.Hostname()
    if err != nil {
        hostname = "def"
    }
    pack = &Package{
        Version:        [2]byte{'V', '1'},
        Timestamp:      time.Now().Unix(),
        HostnameLength: int16(len(hostname)),
        Hostname:       []byte(hostname),
        Body:           []byte(body),
    }
    pack.Length = 10 + pack.HostnameLength + int16(len(pack.Body))
    return
}
func NewScanner(reader io.Reader) (scanner *bufio.Scanner) {
    scanner = bufio.NewScanner(reader)
    scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
        if atEOF {
            return
        }
        if len(data) <= 4 {
            return
        }
        if data[0] == 'V' {
            length := int16(0)
            binary.Read(bytes.NewReader(data[2:4]), binary.BigEndian, &length)
            if int(length)+4 <= len(data) {
                return int(length) + 4, data[:int(length)+4], nil
            }
        }
        return
    })
    return
}
func (p *Package) Unpack(reader io.Reader) error {
    var err error
    err = binary.Read(reader, binary.BigEndian, &p.Version)
    err = binary.Read(reader, binary.BigEndian, &p.Length)
    err = binary.Read(reader, binary.BigEndian, &p.Timestamp)
    err = binary.Read(reader, binary.BigEndian, &p.HostnameLength)
    p.Hostname = make([]byte, p.HostnameLength)
    err = binary.Read(reader, binary.BigEndian, &p.Hostname)
    p.Body = make([]byte, p.Length-10-p.HostnameLength)
    err = binary.Read(reader, binary.BigEndian, &p.Body)
    return err
}
func (p *Package) String() string {
    return fmt.Sprintf("version:%s length:%d timestamp:%d hostname:%s body:%s",
        p.Version,
        p.Length,
        p.Timestamp,
        p.Hostname,
        p.Body,
    )
}
func main() {
    buf := new(bytes.Buffer)
    var test = 0
    go func() {
        for {
            // m.Lock()
            pack := New(strconv.Itoa(test))
            pack.Pack(buf)
            // m.Unlock()
            test++
            time.Sleep(1 * time.Second)
        }
    }()
    for {
        // m.Lock()
        scanner := NewScanner(buf)
        for scanner.Scan() {
            scannedPack := new(Package)
            scannedPack.Unpack(bytes.NewReader(scanner.Bytes()))
            log.Println(scannedPack)
        }
        // m.Unlock()
        time.Sleep(2 * time.Second)
    }
    // if err := scanner.Err(); err != nil {
    //  log.Fatal("无效数据包")
    // }
}




如果这篇文章对你有所帮助,可以通过下边的“打赏”功能进行小额的打赏。

本网站部分内容来源于互联网,如有侵犯版权请来信告知,我们将立即处理。


来说两句吧