微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Golang加头和尾部来解决tcp粘包问题.代码片段示例

package main

import (
	"bufio"
	"encoding/binary"
	"fmt"
	"io"
	"net"
)

var empty []byte

func main() {
	lis,_ := net.Listen("tcp",":1789")
	for {
		con,err := lis.Accept()
		if err != nil {
			continue
		}
		//当建立连接的时候交给registerConn来处理这个链接.
		//想自定义就可以把这个函数重写.
		go registerConn(con)
	}
}

type ConnectionInfo struct {
	Conn     net.Conn
	Buf      *bufio.Reader
	Authfunc func(msg []byte) bool
}

type ConnResolve interface {
	OnceRead() ([]byte,error)
	StillRead()
	Close() error
	AuthFuncation(msg []byte) bool
}

func (self *ConnectionInfo) OnceRead() ([]byte,error) {
	return reader(self.Buf)
}

func (self *ConnectionInfo) AuthFuncation(msg []byte) bool {
	return self.Authfunc(msg)
}

func (self *ConnectionInfo) Close() error {
	return self.Conn.Close()
}

func (self *ConnectionInfo) StillRead() {
	for {
		msg,err := reader(self.Buf)
		if err != nil {
			if err == io.EOF {
				continue
			}
			return
		}
		fmt.Printf("收到的信息: %s\n",string(msg))
	}
}

func registerConn(conn net.Conn) {
	defer conn.Close()
	//这里返回的是一个接口,可以自定义消息处理机制.
	reg := NewconnectionInfo(conn,nil)
	//接入的时候第一次读取认证信息,然后
	msg,err := reg.OnceRead()
	if err != nil {
		return
	}
	if !reg.AuthFuncation(msg) {
		return
	}
	reg.StillRead()
}

func NewconnectionInfo(conn net.Conn,authfunc func(msg []byte) bool) ConnResolve {
	if authfunc == nil {
		authfunc = DefaultAuthFunc
	}
	return &ConnectionInfo{conn,bufio.NewReader(conn),authfunc}
}

func DefaultAuthFunc(msg []byte) bool {
	fmt.Println("开始校验认证信息: ",string(msg))
	return true
}

//reader方法是用来定义读取的流的逻辑的,可以自己按找自己的逻辑定义.
func reader(buf *bufio.Reader) ([]byte,error) {
	head := make([]byte,5)
	_,err := buf.Read(head)
	if err != nil {
		return empty,err
	}
	bodyLen,_ := binary.Uvarint(head)
	line,err := buf.ReadSlice('\n')
	if err != nil {
		return empty,err
	}
	if uint64(len(line)-1) != bodyLen {
		return empty,io.EOF
	}
	return line[:bodyLen],nil
}
func writer(conn net.Conn,msg []byte) (int,error) {
	mgslen := len(msg)
	head := make([]byte,5+mgslen+1)
	binary.PutUvarint(head,uint64(mgslen))
	copy(head[5:],msg)
	head[mgslen] = '\n'
	return conn.Write(head)
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐