九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開(kāi)通VIP
服務(wù)器粘包處理

服務(wù)器的粘包處理

什么是粘包

一個(gè)完成的消息可能會(huì)被TCP拆分成多個(gè)包進(jìn)行發(fā)送,也有可能把多個(gè)小的包封裝成一個(gè)大的數(shù)據(jù)包發(fā)送,這個(gè)就是TCP的拆包和封包問(wèn)題

TCP粘包和拆包產(chǎn)生的原因

  1. 應(yīng)用程序?qū)懭霐?shù)據(jù)的字節(jié)大小大于套接字發(fā)送緩沖區(qū)的大小

  2. 進(jìn)行MSS大小的TCP分段。MSS是最大報(bào)文段長(zhǎng)度的縮寫。MSS是TCP報(bào)文段中的數(shù)據(jù)字段的最大長(zhǎng)度。數(shù)據(jù)字段加上TCP首部才等于整個(gè)的TCP報(bào)文段。所以MSS并不是TCP報(bào)文段的最大長(zhǎng)度,而是:MSS=TCP報(bào)文段長(zhǎng)度-TCP首部長(zhǎng)度

  3. 以太網(wǎng)的payload大于MTU進(jìn)行IP分片。MTU指:一種通信協(xié)議的某一層上面所能通過(guò)的最大數(shù)據(jù)包大小。如果IP層有一個(gè)數(shù)據(jù)包要傳,而且數(shù)據(jù)的長(zhǎng)度比鏈路層的MTU大,那么IP層就會(huì)進(jìn)行分片,把數(shù)據(jù)包分成托干片,讓每一片都不超過(guò)MTU。注意,IP分片可以發(fā)生在原始發(fā)送端主機(jī)上,也可以發(fā)生在中間路由器上。

TCP粘包和拆包的解決策略

  1. 消息定長(zhǎng)。例如100字節(jié)。
  2. 在包尾部增加回車或者空格符等特殊字符進(jìn)行分割,典型的如FTP協(xié)議
  3. 將消息分為消息頭和消息尾。
  4. 其它復(fù)雜的協(xié)議,如RTMP協(xié)議等。

參考文章 (http://blog.csdn.net/initphp/article/details/41948919)

我們的處理方式

解決粘包問(wèn)題有多種多樣的方式, 我們這里的做法是:

  • 發(fā)送方在每次發(fā)送消息時(shí)將消息長(zhǎng)度寫入一個(gè)int32作為包頭一并發(fā)送出去, 我們稱之為Encode
  • 接受方則先讀取一個(gè)int32的長(zhǎng)度的消息長(zhǎng)度信息, 再根據(jù)長(zhǎng)度讀取相應(yīng)長(zhǎng)的byte數(shù)據(jù), 稱之為Decode

在實(shí)驗(yàn)環(huán)境中的主文件夾內(nèi), 新建一個(gè)名為codec的文件夾在其之下新建一個(gè)文件codec.go, 將我們的Encode和Decode方法寫入其中, 這里給出Encode與Decode相應(yīng)的代碼:

codec.go

package codecimport (    "bufio"    "bytes"    "encoding/binary")func Encode(message string) ([]byte, error) {    // 讀取消息的長(zhǎng)度    var length int32 = int32(len(message))    var pkg *bytes.Buffer = new(bytes.Buffer)    // 寫入消息頭    err := binary.Write(pkg, binary.LittleEndian, length)    if err != nil {        return nil, err    }    // 寫入消息實(shí)體    err = binary.Write(pkg, binary.LittleEndian, []byte(message))    if err != nil {        return nil, err    }    return pkg.Bytes(), nil}func Decode(reader *bufio.Reader) (string, error) {    // 讀取消息的長(zhǎng)度    lengthByte, _ := reader.Peek(4)    lengthBuff := bytes.NewBuffer(lengthByte)    var length int32    err := binary.Read(lengthBuff, binary.LittleEndian, &length)    if err != nil {        return "", err    }    if int32(reader.Buffered()) < length+4 {        return "", err    }    // 讀取消息真正的內(nèi)容    pack := make([]byte, int(4+length))    _, err = reader.Read(pack)    if err != nil {        return "", err    }    return string(pack[4:]), nil}

這里就不帖服務(wù)器與客戶端的調(diào)用代碼了, 同學(xué)們自己動(dòng)手試試~

動(dòng)手實(shí)踐是學(xué)習(xí) IT 技術(shù)最有效的方式! 開(kāi)始實(shí)驗(yàn)
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
一篇文章帶你了解Go語(yǔ)言基礎(chǔ)之網(wǎng)絡(luò)編程
golang之tcp自動(dòng)重連
golang表單提交與服務(wù)器的交互
Go 語(yǔ)言高級(jí)網(wǎng)絡(luò)編程
【Go語(yǔ)言實(shí)戰(zhàn)】(4) 簡(jiǎn)簡(jiǎn)單單的幾十行代碼實(shí)現(xiàn) TCP 通信
動(dòng)圖圖解!既然IP層會(huì)分片,為什么TCP層也還要分段?|路由器|ip|tcp|數(shù)據(jù)包|報(bào)文
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服