我正在尝试通过 QDataStream
从客户端向服务器发送图像 (OpenCV Mat
)。第一项是 int,缓冲区的大小。它适用于 10 到 15 张图像,然后服务器读取第一个 int 随机数(通常 ~2^30),这会导致应用程序崩溃。
这是客户端,在一个循环中(图像来自网络摄像头,周期为 500 毫秒):
//1) encode to jpg
cv::vector<uchar> buf;
cv::imencode(".jpg", *mat, buf);
//2) write to buffer
QByteArray buffer;
QDataStream out(&buffer, QIODevice::WriteOnly);
out << int(0); // save place for an int which represents the buffer size
for(cv::vector<uchar>::iterator it = buf.begin(); it != buf.end(); ++it)
{
out << *it; //write each byte
}
out.device()->seek(0); //write the buffer size
out << buffer.size();
qDebug() << "Sent " << buffer.size() << "bytes";
qint64 bytesSent = socket->write(buffer);
if(bytesSent < buffer.size())
{
if(bytesSent != -1)
{
qDebug() << "Transmit Error! Sent " << bytesSent << " out of " << buffer.size();
}
else
{
qDebug() << socket->errorString();
}
}
服务器端:
QDataStream in(socket);
int msgSize = -1;
//first read the size as an int
if(socket->bytesAvailable())
{
in >> msgSize;
}
qDebug() << "Read image size: " << msgSize << "bytes";
//wait until all bytes all available
while(socket->bytesAvailable() < ( qint64 ) ( ( qint64 )msgSize - sizeof(int) ) )
{
if(!socket->waitForReadyRead())
{
qDebug() << "Disconnected: " << socket->errorString();
socket->disconnectFromHost();
break;
}
}
qDebug() << "Bytes recieved: " << msgSize;
QByteArray ba;
quint8 byte;
for(int i = 0; i < msgSize - 1; ++i)
{
in >> byte;
ba.append(byte);
}
cv::Mat imgbuf = cv::Mat(FRAME_WIDTH, FRAME_HEIGHT, CV_8UC3, ba.data());
cv::Mat matImg = cv::imdecode(imgbuf, CV_LOAD_IMAGE_COLOR);
两个套接字都是QTcpSocket
。
输出示例:
The server side:
Read image size: 67551 bytes
Bytes recieved: 67551
Read image size: 56924 bytes
Bytes recieved: 56924
Read image size: 70027 bytes
Bytes recieved: 70027
Read image size: -2046830337 bytes
Bytes recieved: -2046830337
Read image size: -536866742 bytes
Bytes recieved: -536866742
Read image size: 1179207168 bytes
At this point it tries to read 1179207168 bytes.
The client side:
Sent 67551 bytes
Sent 56924 bytes
Sent 70027 bytes
Sent 70277 bytes
Sent 85633 bytes
Sent 65155 bytes
etc ...
只有前三个成功。
最佳答案
首先,我认为您不需要 QDataStream 来完成这项任务。 QDataStream 用于序列化/反序列化 Qt 类型,并且特定于您使用的 Qt 版本。由于您只是想通过网络编写 uchar,因此您可以直接遍历 cv::vector,并直接通过网络写入这些字节(事实上,您也不需要中介 QByteArray,因为您已经有了 byteLength 和你的原始 vector )。
但是,您可以使用 QDataStream(因为您使用的是非常基本的类型,这些类型不太可能在 QDataStream 版本之间发生变化),并且由于您是这样开始的,所以我将提供相应的答案
这看起来更像(客户端):
// 1) encode to jpg
cv::vector<uchar> buf;
cv::imencode(".jpg", *mat, buf);
// 2) write to buffer, your 'protocol' assumes buffer length first, then the data.
// REMEMBER: QDataStream operates on -any- QIODevice, so no need for the extra buffer here
QDataStream out(socket, QIODevice::WriteOnly);
out << buf.size();
cv::vector<uchar>::const_iterator it;
cv::vector<uchar>::const_iterator itEnd = buf.end();
for (it = buf.begin(); it != itEnd; ++it)
out << *it;
服务器端:
QDataStream in(socket, QIODevice::ReadOnly);
cv::vector<uchar> buf;
socket->waitForReadyRead();
qint64 bytesRead = 0;
qint64 size;
in >> size;
buf.reserve(size);
while (buf.size() < size) {
if (!socket->bytesAvailable())
socket->waitForReadyRead();
qint8 byte;
in >> byte;
buf.push_back(byte);
}
cv::Mat imgbuf = cv::Mat(FRAME_WIDTH, FRAME_HEIGHT, CV_8UC3, buf);
cv::Mat matImg = cv::imdecode(imgbuf, CV_LOAD_IMAGE_COLOR);
注意:这一切都是即兴的,它很可能无法编译,而且肯定有更有效的方法来做到这一点,但我认为它让您了解如何进行编译可以着手修复您现有的代码
关于c++ - Qt 客户端-服务器应用程序, “send image” 有问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23569932/