Solution to the golang network socket sticky packet problem
- 2020-06-01 09:59:59
- OfStack
This article illustrates the solution to the golang network socket sticky packet problem with an example. I will share it with you for your reference as follows:
I saw a lot of people asking this question, so I wrote an example today, hoping to help you
First of all, say 1 what is sticky packet: baidu is more popular language refers to the TCP protocol, a number of packet data sent by the sender to the receiver when receiving sticky packet, from the receiving buffer, the head of the last packet data immediately followed by the tail of the first packet data.
The solution is as follows:
Server:
package main
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"net"
)
func main() {
// Listen on port
ln, err := net.Listen("tcp", ":6000")
if err != nil {
fmt.Printf("Listen Error: %s\n", err)
return
}
// Listening to the circulation
for {
// Accept client links
conn, err := ln.Accept()
if err != nil {
fmt.Printf("Accept Error: %s\n", err)
continue
}
// Handle client links
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
// Close links
defer conn.Close()
// The client
fmt.Printf("Client: %s\n", conn.RemoteAddr())
// Message buffer
msgbuf := bytes.NewBuffer(make([]byte, 0, 10240))
// The data buffer
databuf := make([]byte, 4096)
// The length of the message
length := 0
// The length of the message uint32
ulength := uint32(0)
// Data cycle
for {
// Read the data
n, err := conn.Read(databuf)
if err == io.EOF {
fmt.Printf("Client exit: %s\n", conn.RemoteAddr())
}
if err != nil {
fmt.Printf("Read error: %s\n", err)
return
}
fmt.Println(databuf[:n])
// Data is added to the message buffer
n, err = msgbuf.Write(databuf[:n])
if err != nil {
fmt.Printf("Buffer write error: %s\n", err)
return
}
// Message segmentation loop
for {
// The message header
if length == 0 && msgbuf.Len() >= 4 {
binary.Read(msgbuf, binary.LittleEndian, &ulength)
length = int(ulength)
// Check for long messages
if length > 10240 {
fmt.Printf("Message too length: %d\n", length)
return
}
}
// The message body
if length > 0 && msgbuf.Len() >= length {
fmt.Printf("Client messge: %s\n", string(msgbuf.Next(length)))
length = 0
} else {
break
}
}
}
}
Client:
package main
import (
"bytes"
"encoding/binary"
"fmt"
"net"
"time"
)
func main() {
// Link server
conn, err := net.Dial("tcp", "127.0.0.1:6000")
if err != nil {
fmt.Printf("Dial error: %s\n", err)
return
}
// Client information
fmt.Printf("Client: %s\n", conn.LocalAddr())
// Message buffer
msgbuf := bytes.NewBuffer(make([]byte, 0, 1024))
// The message content
message := []byte(" I am a utf-8 The news of the ")
// The length of the message
messageLen := uint32(len(message))
// Total message length
mlen := 4 + len(message)
// write 5 message
for i := 0; i < 10; i++ {
binary.Write(msgbuf, binary.LittleEndian, messageLen)
msgbuf.Write(message)
}
// Single package sent 1 message
conn.Write(msgbuf.Next(mlen))
time.Sleep(time.Second)
// Single package sent 3 message
conn.Write(msgbuf.Next(mlen * 3))
time.Sleep(time.Second)
// Send an incomplete header
conn.Write(msgbuf.Next(2))
time.Sleep(time.Second)
// Send the rest of the message
conn.Write(msgbuf.Next(mlen - 2))
time.Sleep(time.Second)
// Send an incomplete message body
conn.Write(msgbuf.Next(mlen - 6))
time.Sleep(time.Second)
// Send the rest of the message
conn.Write(msgbuf.Next(6))
time.Sleep(time.Second)
// Multiple segments
conn.Write(msgbuf.Next(mlen + 2))
time.Sleep(time.Second)
conn.Write(msgbuf.Next(-2 + mlen - 8))
time.Sleep(time.Second)
conn.Write(msgbuf.Next(8 + 1))
time.Sleep(time.Second)
conn.Write(msgbuf.Next(-1 + mlen + mlen))
time.Sleep(time.Second)
// Close links
conn.Close()
}
I hope this article has been helpful to you in programming Go.