server //服务端解包过程 package main import ( "fmt" "net" "nianbao/protocol" "os" ) func main() { netListen, err := net.Listen("tcp", ":9988") CheckError(err) defer netListen.Close() Log("Waiting for clients") for { conn, err := netListen.Accept() if err != nil { continue } Log(conn.RemoteAddr().String(), " tcp connect success") go handleConnection(conn) } //fmt.Println("dd") } func handleConnection(conn net.Conn) { //声明一个临时缓冲区,用来存储被截断的数据 tmpBuffer := make([]byte, 0) //声明一个管道用于接收解包的数据 readerChannel := make(chan []byte, 16) go reader(readerChannel) buffer := make([]byte, 1500) for { n, err := conn.Read(buffer) if err != nil { Log(conn.RemoteAddr().String(), " connection error: ", err) return } tmpBuffer = protocol.Unpack(append(tmpBuffer, buffer[:n]...), readerChannel) } } func reader(readerChannel chan []byte) { for { select { case data := <-readerChannel: Log(string(data)) } } } func Log(v ...interface{}) { fmt.Println(v...) } func CheckError(err error) { if err != nil { fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) os.Exit(1) } }
client
//客户端发送封包 package main import ( "fmt" "net" "nianbao/protocol" "os" "time" ) func sender(conn net.Conn) { for i := 0; i < 1000; i++ { words := "<?xml version=\"1.0\"?>\n<Envelope xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n <Header>\n <MessageName>FoSecurityResult</MessageName>\n <MessageTime>2021-03-31T15:02:37+08:00</MessageTime>\n </Header>\n <Body>\n <Record>\n <CheckType>1</CheckType>\n <CheckId>3999205072</CheckId>\n <ImageGuid>f55ce2cc43914aeabd828986904f3eed_NUCTECH00120210331000222</ImageGuid>\n <DeviceId>f55ce2cc43914aeabd828986904f3eed</DeviceId>\n <CheckPos>T2G1</CheckPos>\n <Result>R</Result>\n <Department>0</Department>\n <OptId>n7</OptId>\n <Image2DUrl>http://10.37.38.5:1002/202103313999205072/1/150221_000222.jpg</Image2DUrl>\n <Image3DUrl>http://10.37.38.5:1002/202103313999205072/1/150221_000222_3D.jpg</Image3DUrl>\n <SideImage2DUrl>http://10.37.38.5:1002/202103313999205072/1/150221_000222_side.jpg</SideImage2DUrl>\n <TaggedImage2DUrl>http://10.37.38.5:1002/202103313999205072/1/150221_000222_2DManualMark.jpg</TaggedImage2DUrl>\n <TaggedSideImage2DUrl>http://10.37.38.5:1002/202103313999205072/1/150221_000222_2DManualMark_side.jpg</TaggedSideImage2DUrl>\n <TaggedImage3DUrl>http://10.37.38.5:1002/202103313999205072/1/150221_000222_3DManualMark.jpg</TaggedImage3DUrl>\n <CreateTime>2021-03-31T15:02:21+08:00</CreateTime>\n <CheckTime>2021-03-31T15:02:37+08:00</CheckTime>\n </Record>\n </Body>\n</Envelope><?xml version=\"1.0\"?>\n<Envelope xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n <Header>\n <MessageName>FoSecurityResult</MessageName>\n <MessageTime>2021-03-31T15:02:37+08:00</MessageTime>\n </Header>\n <Body>\n <Record>\n <CheckType>1</CheckType>\n <CheckId>3999101496</CheckId>\n <ImageGuid>c193d6034c3b49d69323e306735da0f0_NUCTECH00120210331000318</ImageGuid>\n <DeviceId>c193d6034c3b49d69323e306735da0f0</DeviceId>\n <CheckPos>T1C1</CheckPos>\n <Result>C</Result>\n <Department>0</Department>\n <OptId>n4</OptId>\n <Image2DUrl>http://10.37.38.5:1002/202103313999101496/1/150220_000318.jpg</Image2DUrl>\n <Image3DUrl>http://10.37.38.5:1002/202103313999101496/1/150220_000318_3D.jpg</Image3DUrl>\n <SideImage2DUrl>http://10.37.38.5:1002/202103313999101496/1/150220_000318_side.jpg</SideImage2DUrl>\n <TaggedImage2DUrl>http://10.37.38.5:1002/202103313999101496/1/150220_000318_2DManualMark.jpg</TaggedImage2DUrl>\n <TaggedSideImage2DUrl>http://10.37.38.5:1002/202103313999101496/1/150220_000318_2DManualMark_side.jpg</TaggedSideImage2DUrl>\n <TaggedImage3DUrl>http://10.37.38.5:1002/202103313999101496/1/150220_000318_3DManualMark.jpg</TaggedImage3DUrl>\n <CreateTime>2021-03-31T15:02:20+08:00</CreateTime>\n <CheckTime>2021-03-31T15:02:37+08:00</CheckTime>\n </Record>\n </Body>\n</Envelope><?xml version=\"1.0\"?>\n<Envelope xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n <Header>\n <MessageName>FoSecurityResult</MessageName>\n <MessageTime>2021-03-31T15:02:38+08:00</MessageTime>\n </Header>\n <Body>\n <Record>\n <CheckType>1</CheckType>\n <CheckId>3999102398</CheckId>\n <ImageGuid>b4a29b573be24d5590dd5b2fb6183685_NUCTECH00120210331000155</ImageGuid>\n <DeviceId>b4a29b573be24d5590dd5b2fb6183685</DeviceId>\n <CheckPos>T1D2</CheckPos>\n <Result>C</Result>\n <Department>0</Department>\n <OptId>n8</OptId>\n <Image2DUrl>http://10.37.38.5:1002/202103313999102398/1/150221_000155.jpg</Image2DUrl>\n <Image3DUrl>http://10.37.38.5:1002/202103313999102398/1/150221_000155_3D.jpg</Image3DUrl>\n <SideImage2DUrl>http://10.37.38.5:1002/202103313999102398/1/150221_000155_side.jpg</SideImage2DUrl>\n <TaggedImage2DUrl xsi:nil=\"true\" />\n <TaggedSideImage2DUrl xsi:nil=\"true\" />\n <TaggedImage3DUrl xsi:nil=\"true\" />\n <CreateTime>2021-03-31T15:02:21+08:00</CreateTime>\n <CheckTime>2021-03-31T15:02:37+08:00</CheckTime>\n </Record>\n </Body>\n</Envelope>" conn.Write(protocol.Packet([]byte(words))) //words2 := "<?xmlId:111111:end?><?xmlId:123456:end?>" //words2 := "333333444444555555666666777777888888999999000000:end?>" //conn.Write(protocol.Packet([]byte(words2))) } fmt.Println("send over") } func main() { server := "127.0.0.1:9988" 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) } defer conn.Close() fmt.Println("connect success") go sender(conn) for { time.Sleep(1 * 1e9) } }
package protocol import ( "bytes" "encoding/binary" "fmt" ) const ( ConstHeader = "www.01happy.com" ConstHeaderLength = 15 ConstSaveDataLength = 4 ConstXMLHeader = "<?xml" ConstXMLEnder = "</Envelope>" ConstXMLHeaderLen = 5 ConstXMLEnderLen = 11 ) //封包 func Packet(message []byte) []byte { //fmt.Println(string(message)) return message //return append(append([]byte(ConstHeader), IntToBytes(len(message))...), message...) } //解包 func Unpack(buffer []byte, readerChannel chan []byte) []byte { length := len(buffer) var end int var i int for i = 0; i < length; i = i + 1 { if length < i+ConstXMLHeaderLen { break } if string(buffer[i:i+ConstXMLHeaderLen]) == ConstXMLHeader { for j := i + ConstXMLHeaderLen; j < length; j = j + 1 { if length < j+ConstXMLHeaderLen { data := buffer[i:] fmt.Println("AAAA",data) return buffer[i:] } if string(buffer[j:j+ConstXMLEnderLen]) == ConstXMLEnder { end = j + ConstXMLEnderLen data := buffer[i:end] //fmt.Println("放入chan",data) readerChannel <- data i = end - 1 break } } } } if i == length { return make([]byte, 0) } return buffer[i:] } //解包 func Unpack2(buffer []byte, readerChannel chan []byte) []byte { length := len(buffer) var i int for i = 0; i < length; i = i + 1 { if length < i+ConstHeaderLength+ConstSaveDataLength { break } if string(buffer[i:i+ConstHeaderLength]) == ConstHeader { messageLength := BytesToInt(buffer[i+ConstHeaderLength : i+ConstHeaderLength+ConstSaveDataLength]) if length < i+ConstHeaderLength+ConstSaveDataLength+messageLength { break } data := buffer[i+ConstHeaderLength+ConstSaveDataLength : i+ConstHeaderLength+ConstSaveDataLength+messageLength] readerChannel <- data i += ConstHeaderLength + ConstSaveDataLength + messageLength - 1 } } if i == length { return make([]byte, 0) } return buffer[i:] } //整形转换成字节 func IntToBytes(n int) []byte { x := int32(n) bytesBuffer := bytes.NewBuffer([]byte{}) binary.Write(bytesBuffer, binary.BigEndian, x) return bytesBuffer.Bytes() } //字节转换成整形 func BytesToInt(b []byte) int { bytesBuffer := bytes.NewBuffer(b) var x int32 binary.Read(bytesBuffer, binary.BigEndian, &x) return int(x) }