Application Scenarios
Use custom communication protocol in most TCP communication scenarios
image.png
Sticky Packet Processing Principle: Buffer data sent by clients N times into a single packet by the size of the packet in the request header
For example:
Request header takes up 3 bytes (instruction header 1 byte, packet length 2 bytes), version takes up 1 byte, instruction takes up 2 bytes
The protocol specifies a maximum of 512 bytes for a packet, 1300 bytes for a packet record in the request header, and 1307 bytes for a complete packet. At this time, the server needs to glue the data sent by the client three times.
Code Samples
package server import ( "net" "bufio" "ftj-data-synchro/protocol" "golang.org/x/text/transform" "golang.org/x/text/encoding/simplifiedchinese" "io/ioutil" "bytes" "ftj-data-synchro/logic" "fmt" "strconv" ) /* Client Architecture */ type Client struct { DeviceID string //Flag-only for client connections Conn net.Conn //Connect reader *bufio.Reader //read writer *bufio.Writer //output Data []byte //receive data } func NewClient(conn *net.TCPConn) *Client { reader := bufio.NewReaderSize(conn, 10240) writer := bufio.NewWriter(conn) c := &Client{Conn:conn, reader:reader, writer:writer} return c } /** Data Read (Glue Pack Processing) */ func (this *Client)read() { for { var data []byte var err error //The read command header returns the first four bytes of the input stream without moving the read position data, err = this.reader.Peek(4) if len(data) == 0 || err != nil { continue } //Returns the number of bytes available for reading in the buffer var byteSize = this.reader.Buffered() fmt.Printf("Read byte length:%d\n", byteSize) //Generate a byte array of readable bytes in the buffer data = make([]byte, byteSize) //Read data in buffer this.reader.Read(data) fmt.Printf("Read bytes:%d\n", data) //Save to a new buffer for _, v := range data { this.Data = append(this.Data, v) } if len(this.Data) < 4 { //Packet Buffer Empty this.Data = []byte{} fmt.Printf("Illegal data, no header...\n") continue } data, err = protocol.HexBytesToBytes(this.Data[:4]) instructHead, _ := strconv.ParseUint(string(data), 16, 16) //Instruction Header Validity if uint16(instructHead) != 42330 { fmt.Printf("invalid data\n") //Packet Buffer Empty this.Data = []byte{} continue } data = this.Data[:protocol.HEADER_SIZE] var p = protocol.Decode(data) fmt.Printf("Message body length:%d\n", p.Len) var bodyLength = len(this.Data) /** Determine if the size of the packet buffer is smaller than the size of the packet in the protocol request header If less than, wait for the next client packet to be read, otherwise decode the packet for business logic processing */ if int(p.Len) > len(this.Data) - protocol.HEADER_SIZE { fmt.Printf("body Body length:%d,Read body Body length:%d\n", p.Len, bodyLength) continue } fmt.Printf("Actual processing bytes:%v\n", this.Data) p = protocol.Decode(this.Data) //Logical Processing go this.logicHandler(p) //Packet Buffer Empty this.Data = []byte{} } }
The section to be optimized:
type Client struct { DeviceID string //Flag-only for client connections Conn net.Conn //Connect reader *bufio.Reader //read writer *bufio.Writer //output Data []byte //receive data }
The Data attribute in the structure can be considered for useBytes.BufferRealization.
Golang Standard Library Documentation:https://studygolang.com/pkgdoc
The above is an original article, please indicate the author @Curry
QQ:208275451