首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在QTCPSocket(Qt++)中逐字节传输音频文件

在QTCPSocket(Qt++)中逐字节传输音频文件
EN

Stack Overflow用户
提问于 2017-08-01 04:47:15
回答 1查看 692关注 0票数 0

我需要在套接字中逐字节传输音频文件,而在接收端,我需要正确地安排它。例如,有两个音频文件A和B,我必须从A读取一个字节并进行传输,接下来我必须从B读取第一个字节并传输,然后从A读取第二个字节,然后从B读取第二个字节,这样的传输必须一直进行到EOF,在接收端我必须为A和B组织正确的接收字节。

我在C++(Qt)中为一个音频文件在TCP套接字中尝试了上述方法。

代码语言:javascript
运行
复制
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++;
}

但是在上面的代码中,我填充和编写了一个字节,但是接收端得到了一堆字节(例如接收14000字节)。似乎写套接字中的缓冲区填充最多,然后只发生传输。我要做什么,一次只写一个字节?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-01 06:27:13

您不应该基于逐字节逻辑进行i/o,这是没有效率的。它还可能启用所谓的Nagle算法,它将在发送数据包之前等待更多的数据。我在发送方推荐的是:

代码语言:javascript
运行
复制
 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;
 }

在接收的大小上,您应该有一个合适的缓冲区,这样您就可以进行同样的缓冲。这个例子是关于std向量的,但是它也适用于Qt容器。

代码语言:javascript
运行
复制
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);
}

在开始编写数据之前,您可以在发送端进行安排。

代码语言:javascript
运行
复制
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;
}

在接收方,您可能拥有:

代码语言:javascript
运行
复制
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);
}

当然,您也需要以某种方式传输文件的大小,但是您有了基本的想法。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45429144

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档