七叶笔记 » golang编程 » golang tcp沾包处理之client

golang tcp沾包处理之client

什么是粘包,为什么会有粘包处理

tcp (transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的 socket ,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 即面向流的通信是无消息保护边界的

处理方法

一般有两种处理方式,一种为发送数据流用分隔符,另一种在客户端发包的时候定义包体的长度,服务端按照一定的规则解包

栗子-client

package 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 ()
 }
}
 

相关文章