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

前端之家收集整理的这篇文章主要介绍了Golang加头和尾部来解决tcp粘包问题.代码片段示例前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
  1. package main
  2.  
  3. import (
  4. "bufio"
  5. "encoding/binary"
  6. "fmt"
  7. "io"
  8. "net"
  9. )
  10.  
  11. var empty []byte
  12.  
  13. func main() {
  14. lis,_ := net.Listen("tcp",":1789")
  15. for {
  16. con,err := lis.Accept()
  17. if err != nil {
  18. continue
  19. }
  20. //当建立连接的时候交给registerConn来处理这个链接.
  21. //想自定义就可以把这个函数重写.
  22. go registerConn(con)
  23. }
  24. }
  25.  
  26. type ConnectionInfo struct {
  27. Conn net.Conn
  28. Buf *bufio.Reader
  29. Authfunc func(msg []byte) bool
  30. }
  31.  
  32. type ConnResolve interface {
  33. OnceRead() ([]byte,error)
  34. StillRead()
  35. Close() error
  36. AuthFuncation(msg []byte) bool
  37. }
  38.  
  39. func (self *ConnectionInfo) OnceRead() ([]byte,error) {
  40. return reader(self.Buf)
  41. }
  42.  
  43. func (self *ConnectionInfo) AuthFuncation(msg []byte) bool {
  44. return self.Authfunc(msg)
  45. }
  46.  
  47. func (self *ConnectionInfo) Close() error {
  48. return self.Conn.Close()
  49. }
  50.  
  51. func (self *ConnectionInfo) StillRead() {
  52. for {
  53. msg,err := reader(self.Buf)
  54. if err != nil {
  55. if err == io.EOF {
  56. continue
  57. }
  58. return
  59. }
  60. fmt.Printf("收到的信息: %s\n",string(msg))
  61. }
  62. }
  63.  
  64. func registerConn(conn net.Conn) {
  65. defer conn.Close()
  66. //这里返回的是一个接口,可以自定义消息处理机制.
  67. reg := NewconnectionInfo(conn,nil)
  68. //接入的时候第一次读取认证信息,然后
  69. msg,err := reg.OnceRead()
  70. if err != nil {
  71. return
  72. }
  73. if !reg.AuthFuncation(msg) {
  74. return
  75. }
  76. reg.StillRead()
  77. }
  78.  
  79. func NewconnectionInfo(conn net.Conn,authfunc func(msg []byte) bool) ConnResolve {
  80. if authfunc == nil {
  81. authfunc = DefaultAuthFunc
  82. }
  83. return &ConnectionInfo{conn,bufio.NewReader(conn),authfunc}
  84. }
  85.  
  86. func DefaultAuthFunc(msg []byte) bool {
  87. fmt.Println("开始校验认证信息: ",string(msg))
  88. return true
  89. }
  90.  
  91. //reader方法是用来定义读取的流的逻辑的,可以自己按找自己的逻辑定义.
  92. func reader(buf *bufio.Reader) ([]byte,error) {
  93. head := make([]byte,5)
  94. _,err := buf.Read(head)
  95. if err != nil {
  96. return empty,err
  97. }
  98. bodyLen,_ := binary.Uvarint(head)
  99. line,err := buf.ReadSlice('\n')
  100. if err != nil {
  101. return empty,err
  102. }
  103. if uint64(len(line)-1) != bodyLen {
  104. return empty,io.EOF
  105. }
  106. return line[:bodyLen],nil
  107. }
  108. func writer(conn net.Conn,msg []byte) (int,error) {
  109. mgslen := len(msg)
  110. head := make([]byte,5+mgslen+1)
  111. binary.PutUvarint(head,uint64(mgslen))
  112. copy(head[5:],msg)
  113. head[mgslen] = '\n'
  114. return conn.Write(head)
  115. }

猜你在找的Go相关文章