GoLang?socket網(wǎng)絡(luò)編程傳輸數(shù)據(jù)包時(shí)進(jìn)行長(zhǎng)度校驗(yàn)的方法
正常來(lái)說(shuō),我們發(fā)送和接收數(shù)據(jù)時(shí),是像下面這樣的:
// 發(fā)送端 func main() { conn, _ := net.Dial("tcp", "127.0.0.1:8889") data := []byte("hello world") conn.Write(data) fmt.Println("成功發(fā)送: ", 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)) }
運(yùn)行結(jié)果如下:
這樣看似沒(méi)問(wèn)題,但實(shí)際上還是存在著一定的風(fēng)險(xiǎn)(如數(shù)據(jù)丟失、解析錯(cuò)誤…),這時(shí)就需要在發(fā)送和接受時(shí)對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)來(lái)確保交互的穩(wěn)定性和安全性。
我們通常利用傳輸數(shù)據(jù)的長(zhǎng)度來(lái)進(jìn)行校驗(yàn),思路如下:發(fā)送端先發(fā)送數(shù)據(jù)長(zhǎng)度len1,再發(fā)送數(shù)據(jù)本體。接收端先接收到數(shù)據(jù)長(zhǎng)度len1,再接收到數(shù)據(jù)本體,然后將數(shù)據(jù)本體的程度與數(shù)據(jù)長(zhǎng)度len1進(jìn)行比較,若二者相等則確認(rèn)數(shù)據(jù)傳輸成功。
上代碼
// 發(fā)送端 func main() { conn, _ := net.Dial("tcp", "127.0.0.1:8889") data := []byte("hello world") // 發(fā)送data的長(zhǎng)度len1 len1 := make([]byte, len(data)) dataLen := uint32(len(data)) binary.BigEndian.PutUint32(len1[:4], dataLen) conn.Write(len1[:4]) // 發(fā)送data本體 conn.Write(data) fmt.Println("成功發(fā)送: ", string(data)) }
// 接收端 func main() { listen, _ := net.Listen("tcp", "0.0.0.0:8889") conn, _ := listen.Accept() // 接收到 data 的長(zhǎng)度 len1:= make([]byte, 1024) realLen, _ := conn.Read(len1[:4]) dataLen := binary.BigEndian.Uint32(len1[:4])// 將 data 的長(zhǎng)度由 []byte 轉(zhuǎn)為 uint32 // 接收到 data data := make([]byte, 1024) realLen, _ = conn.Read(data[:dataLen]) // 在這里進(jìn)行校驗(yàn) if realLen != int(dataLen) { fmt.Println("數(shù)據(jù)在傳輸時(shí)出現(xiàn)問(wèn)題") return } fmt.Println("成功接收: ", string(data)) }
這樣,我們就在接收端初步實(shí)現(xiàn)了數(shù)據(jù)的校驗(yàn)。
眾所周知,Read()函數(shù)和Write()函數(shù)都可以實(shí)際傳輸了多少長(zhǎng)度(字節(jié)),所以我們可以根據(jù)這個(gè)來(lái)完善一下數(shù)據(jù)的校驗(yàn)。
思路:在每次傳輸數(shù)據(jù)(Read或Write)時(shí),我們根據(jù)返回的傳輸長(zhǎng)度進(jìn)行判斷。
例如:
realLen, _ := conn.Write(buf[:4]) if realLen != 4 { fmt.Println("數(shù)據(jù)在傳輸時(shí)出現(xiàn)問(wèn)題") return }
realLen, _ = conn.Write(data) if realLen != int(dataLen) { fmt.Println("數(shù)據(jù)在傳輸時(shí)出現(xiàn)問(wèn)題") return }
在我們之前的代碼中完善這個(gè)校驗(yàn):
// 發(fā)送端 func main() { conn, _ := net.Dial("tcp", "127.0.0.1:8889") data := []byte("hello world") // 發(fā)送data的長(zhǎng)度len1 len1 := make([]byte, len(data)) dataLen := uint32(len(data)) binary.BigEndian.PutUint32(len1[:4], dataLen) conn.Write(len1[:4]) // 完善校驗(yàn) if realLen != 4 { fmt.Println("數(shù)據(jù)在傳輸時(shí)出現(xiàn)問(wèn)題") return } // 發(fā)送data本體 conn.Write(data) // 完善校驗(yàn) if realLen != int(dataLen) { fmt.Println("數(shù)據(jù)在傳輸時(shí)出現(xiàn)問(wèn)題") return } fmt.Println("成功發(fā)送: ", string(data)) }
// 接收端 func main() { listen, _ := net.Listen("tcp", "0.0.0.0:8889") conn, _ := listen.Accept() // 接收到 data 的長(zhǎng)度 len1:= make([]byte, 1024) realLen, _ := conn.Read(len1[:4]) dataLen := binary.BigEndian.Uint32(len1[:4])// 將 data 的長(zhǎng)度由 []byte 轉(zhuǎn)為 uint32 // 完善校驗(yàn) if realLen != 4 { fmt.Println("數(shù)據(jù)在傳輸時(shí)出現(xiàn)問(wèn)題") return } // 接收到 data data := make([]byte, 1024) realLen, _ = conn.Read(data[:dataLen]) // 完善校驗(yàn) if realLen != int(dataLen) { fmt.Println("數(shù)據(jù)在傳輸時(shí)出現(xiàn)問(wèn)題") return } // 在這里進(jìn)行校驗(yàn) if realLen != int(dataLen) { fmt.Println("數(shù)據(jù)在傳輸時(shí)出現(xiàn)問(wèn)題") return } fmt.Println("成功接收: ", string(data)) }
這樣,就實(shí)現(xiàn)了對(duì)數(shù)據(jù)的長(zhǎng)度的校驗(yàn)。
到此這篇關(guān)于GoLang socket網(wǎng)絡(luò)編程傳輸數(shù)據(jù)包時(shí)如何進(jìn)行長(zhǎng)度校驗(yàn)的文章就介紹到這了,更多相關(guān)GoLang socket長(zhǎng)度校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在golang中使用Sync.WaitGroup解決等待的問(wèn)題
這篇文章主要介紹了在golang中使用Sync.WaitGroup解決等待的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04關(guān)于升級(jí)go1.18的goland問(wèn)題詳解
作為一個(gè)go語(yǔ)言程序員,覺(jué)得自己有義務(wù)為go新手開(kāi)一條更簡(jiǎn)單便捷的上手之路,下面這篇文章主要給大家介紹了關(guān)于升級(jí)go1.18的goland問(wèn)題的相關(guān)資料,需要的朋友可以參考下2022-11-11golang interface{}類(lèi)型轉(zhuǎn)換的實(shí)現(xiàn)示例
在Go語(yǔ)言中,類(lèi)型轉(zhuǎn)換可以通過(guò)斷言、顯式、隱式和強(qiáng)制四種方式實(shí)現(xiàn),針對(duì)interface{}類(lèi)型轉(zhuǎn)換為float32或float64,需要使用type斷言或reflect包處理,感興趣的可以了解一下2024-10-10Go語(yǔ)言操作數(shù)據(jù)庫(kù)及其常規(guī)操作的示例代碼
這篇文章主要介紹了Go語(yǔ)言操作數(shù)據(jù)庫(kù)及其常規(guī)操作的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04Go中的new()和make()函數(shù)區(qū)別及底層原理詳解
這篇文章主要為大家介紹了Go中的new()和make()函數(shù)區(qū)別及底層原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09服務(wù)器端Go程序?qū)﹂L(zhǎng)短鏈接的處理及運(yùn)行參數(shù)的保存
這篇文章主要介紹了服務(wù)器端Go程序?qū)﹂L(zhǎng)短鏈接的處理及運(yùn)行參數(shù)的保存,這里針對(duì)使用Go語(yǔ)言編寫(xiě)的Socket服務(wù)器進(jìn)行實(shí)例說(shuō)明,需要的朋友可以參考下2016-03-03intelliJ?idea安裝go開(kāi)發(fā)環(huán)境并搭建go項(xiàng)目(打包)全過(guò)程
最近在配置idea開(kāi)發(fā)go語(yǔ)言時(shí)碰到很多問(wèn)題,所以這里給大家總結(jié)下,這篇文章主要給大家介紹了關(guān)于intelliJ?idea安裝go開(kāi)發(fā)環(huán)境并搭建go項(xiàng)目(打包)的相關(guān)資料,需要的朋友可以參考下2023-10-10