前端之家收集整理的这篇文章主要介绍了
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)
}