人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動態(tài)

go語言處理TCP拆包/粘包的具體實現(xiàn)

發(fā)布日期:2022-02-04 15:49 | 文章來源:源碼之家

part 1

最近在學習go自帶的rpc,看完了一遍想著自己實現(xiàn)一個codec,也就是自定義消息的序列化和反序列化。消息的序列化和反序列化涉及到兩步:

1、從網(wǎng)絡(luò)中讀取數(shù)據(jù)和將數(shù)據(jù)寫到網(wǎng)絡(luò)中;

2、根據(jù)拿到的二進制數(shù)據(jù)反序列化以及把現(xiàn)有的對象序列化成二進制數(shù)據(jù)。而這個過程中就需要處理TCP的拆包粘包了。

TCP的拆包/粘包也算是網(wǎng)絡(luò)編程中一個比較基礎(chǔ)的問題了,具體的問題含義和解決方式也不再詳細描述了。雖然作為實現(xiàn)應(yīng)用層邏輯的程序員可能根本不需要關(guān)心這個,作為中間件的開發(fā),同時也出于學習go語言的目的,還是稍微進行一下練習。

part 2

TCP拆包粘包的解決思路:在讀取數(shù)據(jù)時,將讀取到的二進制數(shù)據(jù)在正確的位置進行分割即可。這里直接使用head+body的方式,也就是在發(fā)送數(shù)據(jù)時先將整個數(shù)據(jù)的大小附加在數(shù)據(jù)前,就像這樣:

+++++++++++++++++++++++++++++++++++++
size (2 bytes)? | body (size bytes)
+++++++++++++++++++++++++++++++++++++

這里將數(shù)據(jù)包的size作為head
注:這里舉的例子里,size占2個byte;size具體占用的byte數(shù)可以根據(jù)實際情況決定

part 3

server具體實現(xiàn):

func doConn(conn net.Conn) {
 var (
  buffer = bytes.NewBuffer(make([]byte, 0, BUF_SIZE)) //buffer用來緩存讀取到的數(shù)據(jù)
  readBytes = make([]byte, BUF_SIZE) //readBytes用來接收每次讀取的數(shù)據(jù),每次讀取完成之后將readBytes添加到buffer中
  isHead = true //用來標識當前的狀態(tài):正在處理size部分還是body部分
  bodyLen = 0 //表示body的長度
 )
 for {
  //首先讀取數(shù)據(jù)
  readByteNum, err := conn.Read(readBytes)
  if err != nil {
log.Fatal(err)
return
  }
  buffer.Write(readBytes[0:readByteNum])//將讀取到的數(shù)據(jù)放到buffer中
  
  // 然后處理數(shù)據(jù)
  for {
if isHead {
 if buffer.Len() >= HEAD_SIZE {
  isHead = false
  head := make([]byte, HEAD_SIZE)
  _, err = buffer.Read(head)
  if err != nil {log.Fatal(err)return
  }
  bodyLen = int(binary.BigEndian.Uint16(head))
 } else {
  break;
 }
}
if !isHead {
 if buffer.Len() >= bodyLen {
  body := make([]byte, bodyLen)
  _, err = buffer.Read(body[:bodyLen])
  if err != nil {log.Fatal(err)return
  }
  fmt.Println("received body: " + string(body[:bodyLen]))
  isHead = true
 } else {
  break;
 }
}
  }
 }
 
 func HandleTcp() {
 listener, err := net.Listen("tcp", ":1234")
 if err != nil {
  log.Fatal(err)
  return
 }
 log.Println("start listening on 1234")
 for {
  conn, err := listener.Accept()
  if err != nil {
log.Fatal(err)
return
  }
  go doConn(conn)
 }
}

client具體實現(xiàn):

func SendStringwithTcp(arg string) error {
 conn, err := net.Dial("tcp", ":1234")
 if err != nil {
  log.Fatal(err)
  return err
 }
 head := make([]byte, server.HEAD_SIZE)
 content := []byte(arg)
 headSize := len(content)
 binary.BigEndian.PutUint16(head, uint16(headSize))
 //先寫入head部分,再寫入body部分
 _, err = conn.Write(head)
 if err != nil {
  log.Fatal(err)
  return err
 }
 _, err = conn.Write(content)
 if err != nil {
  log.Fatal(err)
  return err
 }
 return nil
}

到此這篇關(guān)于go語言處理TCP拆包/粘包的文章就介紹到這了,更多相關(guān)go語言 TCP拆包/粘包內(nèi)容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!

國外服務(wù)器租用

版權(quán)聲明:本站文章來源標注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學習參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實時開通

自選配置、實時開通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專屬顧問服務(wù)

1對1客戶咨詢顧問

在線
客服

在線客服:7*24小時在線

客服
熱線

400-630-3752
7*24小時客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部