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