1. 程式人生 > >tcp-資料包

tcp-資料包

我們往往使用tcp協議傳輸資料,都會自定義一個包裹,本次分享下對包的理解,其基本結構如下:

在傳送端,我們只需要將完整的包裹一次傳送出去即可,eg

    // 位元組
    QByteArray bytes;    
    
    PackageInfo info;
    info.exUse_int = 1000;
    info.exUse_char = '1';
    // bodyLen 非定長
    info.dataSize = buffer.size();

    QDataStream stream(&bytes,QIODevice::WriteOnly);
    // head
    stream << info.exUse_int << info.exUse_char << info.dataSize;
    // body
    bytes.append(buffer.data());
 
    socket->write(bytes);

接受時,由於傳送端告知傳送的資料總位元組數,以及body位元組數,所以我們可以在接受端判斷接收,直到完整接收。

    if(bytesAvailable() <= 0)
    {
        return;
    }
    // 總快取,每次不滿就存入,清空問題待處理
    static QByteArray bytes; 

    // head,定長
    const static int headLen = sizeof(unsigned int) + sizeof(unsigned char) + sizeof(qint64);

    QByteArray t_bytes = readAll();
    bytes.append(t_bytes);
    if(bytes.size() < headLen)
    {
        // 繼續快取
        return;
    }

    // head已經完整get,獲取真實資料長度
    PackageInfo info;
    QDataStream stream(&bytes, QIODevice::ReadOnly);
    stream >> info.exUse_int >> info.exUse_char >> info.dataSize;

    // 讀滿
    if(bytes.size() < info.dataSize + headLen)
    {
        // 繼續快取
        return;
    }

    // bodyData
    QByteArray dataBytes = bytes.right(bytes.size() - headLen);
    
    // to do

我們一次傳送很大的包裹,接收時是多次的,因為,像tcp這種水龍頭流水,你用杯子接水,至於你接了多少水不可控。因此我們使用靜態變數儲存,或者成員變數,每次填充到快取中並比較要接收的大小,直到完整get即可。這裡就是告訴客戶端,你需要接收多大,一個完整的包裹。

關於Tcp協議,粘包問題,等仍需要處理。至於涉及的高併發等深入問題仍需要學習。