QTCPSocket(Qt-C++)中的音频文件逐字节传输
Audio file transfer byte by byte in QTCPSocket(Qt-C++)
我需要在套接字和接收器侧逐字节传输音频文件,我需要正确安排它。例如,有两个音频文件 A 和 B,我必须从 A 读取一个字节并传输,接下来我必须从 B 读取第一个字节并传输,然后从 A 读取第二个字节,从 B 读取第二个字节,就像这样传输必须完成直到 EOF,在接收器端,我必须为 A 和 B 组织正确接收的字节。
上面的一个我在TCP套接字中尝试了C++(Qt(中的一个音频文件。
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 字节(。似乎写套接字中的缓冲区填充最大值,然后只发生传输。我必须做什么,一次只写一个字节?
你不应该基于逐字节逻辑进行 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;
}
在接收大小上,您应该有一个不错的缓冲区,以便您可以执行相同的缓冲。该示例是 std 向量,但它也可能适用于 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);
}
当然,您还需要以某种方式传输文件的大小,但您得到了基本的想法。
相关文章:
- 在UNIX系统中使用DIR查找文件的字节大小
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 如何在文件中查找字节序列
- 读取文件中所有可能的十六进制 16 字节序列并打印每个序列
- 使用 stbi_write_png,如何将 0 和 1 的矩形字节数组转换为单色 png 文件?
- 如何使用 fprintf 将连续的 512 字节保存到文件中
- 用于 progmem 的C++和头文件压缩的 Web 文件字节数组
- 为什么未关闭的文件大小为 4 字节
- 我能确定从文件中读取的 32 字节二进制数据等于 256 位吗?
- Ascii .txt文件到字节数组 - C++
- 多部分/表单数据丢失大文件的字节
- 我该如何循环遍历我的数组(缓冲区——包含一个文本文件),并将其打印成30字节的块
- 程序错误地读取了二进制文件的一个字节
- 如何从 C 或 C++ 格式的文件中删除字节?
- C++ - 将任何文件的字节读取到无符号字符数组中
- ofstream将额外的零字节写入Unix服务器上的文件
- 传输文件一次又一次地发送相同的字节
- 编码大于原始文本:如何获取零和一的字符串并将它们作为实际字节写入文件
- 查找二进制文件中字节序列的所有匹配项
- 如何从 GDI+ 图元文件对象获取原始图元文件字节