GoLang socket网络编程传输数据包时进行长度校验的方法
正常来说,我们发送和接收数据时,是像下面这样的:
// 发送端 func main() { conn, _ := net.Dial("tcp", "127.0.0.1:8889") data := []byte("hello world") conn.Write(data) fmt.Println("成功发送: ", string(data)) }
// 接收端 func main() { listen, _ := net.Listen("tcp", "0.0.0.0:8889") conn, _ := listen.Accept() data := make([]byte, 1024) conn.Read(data) fmt.Println("成功接收: ", string(data)) }
运行结果如下:
这样看似没问题,但实际上还是存在着一定的风险(如数据丢失、解析错误…),这时就需要在发送和接受时对数据进行校验来确保交互的稳定性和安全性。
我们通常利用传输数据的长度来进行校验,思路如下:发送端先发送数据长度len1,再发送数据本体。接收端先接收到数据长度len1,再接收到数据本体,然后将数据本体的程度与数据长度len1进行比较,若二者相等则确认数据传输成功。
上代码
// 发送端 func main() { conn, _ := net.Dial("tcp", "127.0.0.1:8889") data := []byte("hello world") // 发送data的长度len1 len1 := make([]byte, len(data)) dataLen := uint32(len(data)) binary.BigEndian.PutUint32(len1[:4], dataLen) conn.Write(len1[:4]) // 发送data本体 conn.Write(data) fmt.Println("成功发送: ", string(data)) }
// 接收端 func main() { listen, _ := net.Listen("tcp", "0.0.0.0:8889") conn, _ := listen.Accept() // 接收到 data 的长度 len1:= make([]byte, 1024) realLen, _ := conn.Read(len1[:4]) dataLen := binary.BigEndian.Uint32(len1[:4])// 将 data 的长度由 []byte 转为 uint32 // 接收到 data data := make([]byte, 1024) realLen, _ = conn.Read(data[:dataLen]) // 在这里进行校验 if realLen != int(dataLen) { fmt.Println("数据在传输时出现问题") return } fmt.Println("成功接收: ", string(data)) }
这样,我们就在接收端初步实现了数据的校验。
众所周知,Read()函数和Write()函数都可以实际传输了多少长度(字节),所以我们可以根据这个来完善一下数据的校验。
思路:在每次传输数据(Read或Write)时,我们根据返回的传输长度进行判断。
例如:
realLen, _ := conn.Write(buf[:4]) if realLen != 4 { fmt.Println("数据在传输时出现问题") return }
realLen, _ = conn.Write(data) if realLen != int(dataLen) { fmt.Println("数据在传输时出现问题") return }
在我们之前的代码中完善这个校验:
// 发送端 func main() { conn, _ := net.Dial("tcp", "127.0.0.1:8889") data := []byte("hello world") // 发送data的长度len1 len1 := make([]byte, len(data)) dataLen := uint32(len(data)) binary.BigEndian.PutUint32(len1[:4], dataLen) conn.Write(len1[:4]) // 完善校验 if realLen != 4 { fmt.Println("数据在传输时出现问题") return } // 发送data本体 conn.Write(data) // 完善校验 if realLen != int(dataLen) { fmt.Println("数据在传输时出现问题") return } fmt.Println("成功发送: ", string(data)) }
// 接收端 func main() { listen, _ := net.Listen("tcp", "0.0.0.0:8889") conn, _ := listen.Accept() // 接收到 data 的长度 len1:= make([]byte, 1024) realLen, _ := conn.Read(len1[:4]) dataLen := binary.BigEndian.Uint32(len1[:4])// 将 data 的长度由 []byte 转为 uint32 // 完善校验 if realLen != 4 { fmt.Println("数据在传输时出现问题") return } // 接收到 data data := make([]byte, 1024) realLen, _ = conn.Read(data[:dataLen]) // 完善校验 if realLen != int(dataLen) { fmt.Println("数据在传输时出现问题") return } // 在这里进行校验 if realLen != int(dataLen) { fmt.Println("数据在传输时出现问题") return } fmt.Println("成功接收: ", string(data)) }
这样,就实现了对数据的长度的校验。
到此这篇关于GoLang socket网络编程传输数据包时如何进行长度校验的文章就介绍到这了,更多相关GoLang socket长度校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
golang结构化日志log/slog包之slog.Record的用法简介
这篇文章主要为大家详细介绍了golang结构化日志log/slog包中slog.Record结构体的使用方法和需要注意的点,文中的示例代码讲解详细,需要的可以学习一下2023-10-10
最新评论