2017-08-01 113 views
0

我需要字節插座傳輸的音頻文件的字節和在接收端我需要妥善安排。例如,有兩個音頻文件A和B,I必須從A和傳送讀一個字節,接下來我要讀從B和傳輸第一字節,從A這樣轉印有然後第二個字節和第二字節從乙做直至EOF,在接收器側予必須組織爲A和B.音頻文件傳輸字節

上述一個I在C++(QT)在TCP套接字試圖爲一個音頻文件正確接收字節。

QString path = "a4.wav"; 
QFile inputFile(path); 
inputFile.open(QIODevice::ReadOnly); 

QByteArray block; 
QDataStream out(&block, QIODevice::WriteOnly); 
out.setVersion(QDataStream::Qt_5_4); 

QByteArray q = inputFile.readAll(); 
block.append(q); 
inputFile.close(); 

out.device()->seek(0); 

qint32 x = 0; 
unsigned int i = 0; 
while (x < block.size()) { 
    qint32 y = socket->write(&block.data()[i],1); //Filling one byte in socket to write 
    x += y; 
    //qDebug() << y; 
    //qDebug() << x; // summary size you send, so you can check recieved and replied sizes 
    i++; 
} 

但這裏在上面的代碼中,我填充和寫一個字節,但接收機側我得到一串字節(例如接收14000bytes)。看起來寫入插槽中的緩衝區填滿了最大值,然後只有傳輸正在發生。我必須做什麼,一次只寫一個字節?

+0

爲什麼你把文件讀入字節數組●然後複製它阻止?你爲什麼打開DataStream'out'? –

+0

沒有人做每包TCP一個字節。 TCP是一個流,所以網絡設備可以根據需要進行分片和粘貼。可以使用UDP,但仍然浪費,因爲對於每個字節,您還會發送長度爲20到40個字節的數據包標頭。 – Velkan

回答

2

你不應該被字節邏輯做I O基於/的字節,它是沒有效率。它也可能啓用所謂的Nagle算法,它將在發送數據包之前等待更多的數據。我推薦在發送端:

QByte * p = buffer.data(); 
int sizeLeft = static_cast<int>(buffer.size()); 
while (sizeLeft > 0) { 
     int n = socket.send(p, sizeLeft); 
     if (n < 0) { 
      // Error 
      return false; // or throw exception 
     } 
     p += n; 
     sizeLeft -= n; 
} 

在接收大小你應該有一個體面的緩衝區,所以你可以做同樣的緩衝。這個例子是性病載體,但它可能適用於Qt容器以及

int appendReceived(QSocket &socket, std::vector<std::uint32_t> buffer, int maxRecvLength) { 
    size_t prevSize = buffer.size(); 
    buffer.resize(prevSize + maxRecvLength); 
    int n = socket.recv(buffer.data() + prevSize, maxRecvLength); 
    if (n < 0) { 
     // Error 
     return n; // or throw exception 
    } 
    buffer.resize(prevSize + n); 
} 

你可以開始寫數據之前可能做對發送方的安排。

std::vector<std::uint8_t> mergeVectors(const std::vector<std::uint8_t> &a, const std::vector<std::uint8_t> &b) { 
    std::vector<std::uint8_t> result; 
    result.reserve(a.size() + b.size())); 
    size_t minSize = std::min(a.size(), b.size()); 
    for(size_t i = 0; i < minSize; ++i) { 
     result.push_back(a[i]); 
     result.push_back(b[i]); 
    } 
    for (size_t i = minSize; i < a.size(); ++i) { 
     result.push_back(a[i]); 
    } 
    for (size_t i = minSize; i < b.size(); ++i) { 
     result.push_back(b[i]); 
    } 
    return result; 
} 

在接收端,你可能有:

void splitAndRemoveFront(std::vector<std::uint8_t> &buffer, std::vector<std::uint8_t> &a, std::vector<std::uint8_t> &b, size_t asize, size_t bsize) { 
    assert(buffer.size() >= asize + bsize); 
    size_t minSize = std::min(asize, bsize); 
    a.reserve(a.size() + asize); 
    b.reserve(b.size() + bsize); 
    auto p = buffer.begin(); 
    for(size_t i = 0; i < minSize; ++i) { 
     a.push_back(*p++); 
     b.push_back(*p++); 
    } 
    for (size_t i = minSize; i < asize; ++i) { 
     a.push_back(*p++); 
    } 
    for (size_t i = minSize; i < bsize; ++i) { 
     b.push_back(*p++); 
    } 
    buffer.erase(buffer.begin(), p); 
} 

當然,你也將需要以某種方式傳輸文件的大小,但你得到的基本思路。

+0

好的編碼器:) :) –