tcp (transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的 socket ,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 即面向流的通信是无消息保护边界的
一般有两种处理方式,一种为发送数据流用分隔符,另一种在客户端发包的时候定义包体的长度,服务端按照一定的规则解包
栗子-clientpackage main
import (
" bytes "
" encoding /binary"
"fmt"
"net"
"os"
)
type PackageHeader struct {
ServiceID uint32 // service id
Command uint32 // operation Command code
Code int32 // error code
Len uint16 // body length
}
type Package struct {
H PackageHeader
B string
}
func (p Package) Marshal() (* byte s. Buffer , error) {
var (
err error
buf *bytes.Buffer
)
buf = &bytes.Buffer{}
err = binary.Write(buf, binary.LittleEndian, p.H)
if err != nil {
return nil, err
}
buf.WriteByte((byte)(len(p.B)))
buf.WriteString(p.B)
return buf, nil
}
func main() {
server := "127.0.0.1:9988"
for i := 0; i < 100; i++ {
tcpAddr, err := net.ResolveTCPAddr("tcp4", server)
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
os.Exit(1)
}
conn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
os.Exit(1)
}
body := "abcdedfesabcdedfesabcdedfesabcdedfesabcdedfesabcdedfesabcdedfesabcdedfesabcdedfesAAAA"
pkg := Package{}
pkg.B = body
pkg.H = PackageHeader{
ServiceID:1, // service id
Command:1, // operation command code
Code :1, // error code
Len: uint16(len(pkg.B)) + 1, // body length
}
buffer,err := pkg.Marshal()
if err != nil {
fmt.Println(err.Error())
} else {
conn.Write(buffer.Bytes())
}
conn. Close ()
}
}