tcp_msg.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package network
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "io"
  6. "math"
  7. )
  8. // --------------
  9. // | len | data |
  10. // --------------
  11. type MsgParser struct {
  12. lenMsgLen int
  13. minMsgLen uint32
  14. maxMsgLen uint32
  15. littleEndian bool
  16. }
  17. //NewMsgParser 1
  18. func NewMsgParser() *MsgParser {
  19. p := new(MsgParser)
  20. p.lenMsgLen = 2
  21. p.minMsgLen = 1
  22. p.maxMsgLen = 4096
  23. p.littleEndian = false
  24. return p
  25. }
  26. // SetMsgLen It's dangerous to call the method on reading or writing
  27. func (p *MsgParser) SetMsgLen(lenMsgLen int, minMsgLen uint32, maxMsgLen uint32) {
  28. if lenMsgLen == 1 || lenMsgLen == 2 || lenMsgLen == 4 {
  29. p.lenMsgLen = lenMsgLen
  30. }
  31. if minMsgLen != 0 {
  32. p.minMsgLen = minMsgLen
  33. }
  34. if maxMsgLen != 0 {
  35. p.maxMsgLen = maxMsgLen
  36. }
  37. var max uint32
  38. switch p.lenMsgLen {
  39. case 1:
  40. max = math.MaxUint8
  41. case 2:
  42. max = math.MaxUint16
  43. case 4:
  44. max = math.MaxUint32
  45. }
  46. if p.minMsgLen > max {
  47. p.minMsgLen = max
  48. }
  49. if p.maxMsgLen > max {
  50. p.maxMsgLen = max
  51. }
  52. }
  53. // SetByteOrder It's dangerous to call the method on reading or writing
  54. func (p *MsgParser) SetByteOrder(littleEndian bool) {
  55. p.littleEndian = littleEndian
  56. }
  57. // Read goroutine safe
  58. func (p *MsgParser) Read(conn io.Reader) ([]byte, error) {
  59. var b [4]byte
  60. bufMsgLen := b[:p.lenMsgLen]
  61. // read len
  62. if _, err := io.ReadFull(conn, bufMsgLen); err != nil {
  63. return nil, err
  64. }
  65. // parse len
  66. var msgLen uint32
  67. switch p.lenMsgLen {
  68. case 1:
  69. msgLen = uint32(bufMsgLen[0])
  70. case 2:
  71. if p.littleEndian {
  72. msgLen = uint32(binary.LittleEndian.Uint16(bufMsgLen))
  73. } else {
  74. msgLen = uint32(binary.BigEndian.Uint16(bufMsgLen))
  75. }
  76. case 4:
  77. if p.littleEndian {
  78. msgLen = binary.LittleEndian.Uint32(bufMsgLen)
  79. } else {
  80. msgLen = binary.BigEndian.Uint32(bufMsgLen)
  81. }
  82. }
  83. // check len
  84. if msgLen > p.maxMsgLen {
  85. return nil, errors.New("message too long")
  86. } else if msgLen < p.minMsgLen {
  87. return nil, errors.New("message too short")
  88. }
  89. // data
  90. msgData := make([]byte, msgLen)
  91. if _, err := io.ReadFull(conn, msgData); err != nil {
  92. return nil, err
  93. }
  94. return msgData, nil
  95. }
  96. // Write goroutine safe
  97. func (p *MsgParser) Write(conn io.Writer, args ...[]byte) error {
  98. // get len
  99. var msgLen uint32
  100. for i := 0; i < len(args); i++ {
  101. msgLen += uint32(len(args[i]))
  102. }
  103. // check len
  104. if msgLen > p.maxMsgLen {
  105. return errors.New("message too long")
  106. } else if msgLen < p.minMsgLen {
  107. return errors.New("message too short")
  108. }
  109. msg := make([]byte, uint32(p.lenMsgLen)+msgLen)
  110. // write len
  111. switch p.lenMsgLen {
  112. case 1:
  113. msg[0] = byte(msgLen)
  114. case 2:
  115. if p.littleEndian {
  116. binary.LittleEndian.PutUint16(msg, uint16(msgLen))
  117. } else {
  118. binary.BigEndian.PutUint16(msg, uint16(msgLen))
  119. }
  120. case 4:
  121. if p.littleEndian {
  122. binary.LittleEndian.PutUint32(msg, msgLen)
  123. } else {
  124. binary.BigEndian.PutUint32(msg, msgLen)
  125. }
  126. }
  127. // write data
  128. l := p.lenMsgLen
  129. for i := 0; i < len(args); i++ {
  130. copy(msg[l:], args[i])
  131. l += len(args[i])
  132. }
  133. _, err := conn.Write(msg)
  134. return err
  135. }