gpt4 book ai didi

c++ - 在 Windows 7 上通过 QTcpSocket 流式传输图像

转载 作者:可可西里 更新时间:2023-11-01 02:43:55 27 4
gpt4 key购买 nike

我正在尝试基于 QTcpSocket 创建两个测试应用程序,一个流式传输(未压缩)图像的服务器和一个接收它们的客户端。

我的代码主要取自Qts Fortune Client ExampleFortune Server Example .我已经剪掉了所有的gui。我的服务器没有打开连接、发送一笔财富然后立即关闭它,而是保持连接打开并持续流式传输我的图像。客户端只是从 QTcpSocket 中读取图像,然后丢弃它们。

我发送的图像是 800x600 RGB(=1440000 字节),我会尽可能频繁地发送它。每次发送之前都会从文件中读取图像,我没有使用任何压缩。

服务器似乎在正常发送图像。但是客户端接收它们的速度太慢,每秒 1-4 帧,而且有时似乎没有接收到任何数据,这反过来导致我的服务器使用大量内存(因为客户端读取速度不如服务器正在写入)。

我试过在不同的机器上运行我的服务器和客户端,并且都在一台机器上运行,两种设置都会产生同样的问题。

在 Linux 机器上运行我的应用程序时,客户端以更高的速率接收图像(假设是每秒 14 帧)。客户端读取的速度似乎与服务器写入的速度一样快。

任何人都可以帮助阐明这个问题吗?

  1. 如何加快数据传输速度? (不使用压缩)
  2. 如何让客户端读取的速度与服务器写入的速度一样快?
  3. 我怎样才能让它在我的 Windows 机器上保持稳定? (没有突然的停顿......)在客户端的控制台窗口中单击有时似乎会“唤醒”应用程序 btw。 ^^

这是我的代码:

服务器:

主要.cpp

#include <iostream>
#include <QCoreApplication>
#include "Server.h"

int main(int argc, char *argv[]){
QCoreApplication app(argc, argv);
QString ipaddress = QString(argv[1]);
int port = atoi(argv[2]);
Server* server = new Server(ipaddress, port);
int retVal = app.exec();
return retVal;
}

服务器.h

#ifndef SERVER_H_
#define SERVER_H_

#include <QObject>

QT_BEGIN_NAMESPACE
class QTcpServer;
class QNetworkSession;
class QTcpSocket;
class QTimer;
QT_END_NAMESPACE

class Server : public QObject
{
Q_OBJECT

public:
Server(QString ipAddress, int port, QObject *parent = 0);

private slots:
void newConnectionSlot();
void sendSlot();

private:
QTcpServer *mTcpServer;
QTcpSocket *mTcpSocket;
QTimer *mSendTimer;
};

#endif /* SERVER_H_ */

服务器.cpp

#include "Server.h"
#include <iostream>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
#include <QDateTime>
#include <QSettings>
#include <highgui.h>

Server::Server(QString ipAddress, int port, QObject *parent) :
QObject(parent), mTcpServer(0), mTcpSocket(0)
{
mTcpServer = new QTcpServer(this);
connect(mTcpServer, SIGNAL(newConnection()), this, SLOT(newConnectionSlot()));
if (!mTcpServer->listen(QHostAddress(ipAddress), port)) {
std::cout << "Unable to start the server: " << mTcpServer->errorString().toStdString() << std::endl;
return;
}

std::cout << "The server is running on\n\nIP: "<< ipAddress.toStdString()
<< "\nport: " << mTcpServer->serverPort() << "\n\nRun the Client now.\n" << std::endl;
}

void Server::newConnectionSlot()
{
mTcpSocket = mTcpServer->nextPendingConnection();
connect(mTcpSocket, SIGNAL(disconnected()),
mTcpSocket, SLOT(deleteLater()));

// setup timer to send data at a given interval
mSendTimer = new QTimer(this);
connect(mSendTimer, SIGNAL(timeout()),
this, SLOT(sendSlot()));
mSendTimer->start(40);
}

void Server::sendSlot()
{
if(!mTcpSocket)
return;

//know that the image is this big
int width = 800;
int height = 600;
int nChannels = 3;
int depth = 8;
qint64 blockSize = 1440000; //in bytes

qint64 imagesInQue = mTcpSocket->bytesToWrite()/blockSize;
int maxPendingImages = 25;
if(imagesInQue > maxPendingImages)
{
std::cout << "Dumping." << std::endl;
return;
}

//load image
IplImage* img = cvLoadImage("pic1_24bit.bmp");
if(!img)
std::cout << "Error loading image " << std::endl;;

//send data
quint64 written = mTcpSocket->write(img->imageData, img->imageSize);

//clean up
cvReleaseImage( &img );
}

客户:

主要.cpp

#include <iostream>
#include <QCoreApplication>

#include "Client.h"

int main(int argc, char *argv[]){
QCoreApplication app(argc, argv);
QString ipaddress = QString(argv[1]);
int port = atoi(argv[2]);
Client* client = new Client(ipaddress, port);
int retVal = app.exec();
}

客户端.h

#ifndef CLIENT_H_
#define CLIENT_H_

#include <QObject>
#include <QAbstractSocket>

QT_BEGIN_NAMESPACE
class QTcpSocket;
QT_END_NAMESPACE

class Client : public QObject
{
Q_OBJECT
public:
Client(QString ipAddress, int port, QObject *parent=0);

private slots:
void readSlot();
void displayErrorSlot(QAbstractSocket::SocketError);

private:
QTcpSocket *mTcpSocket;
QString mIpAddress;
int mPort;
};

#endif /* CLIENT_H_ */

客户端.cpp

#include "Client.h"
#include <iostream>
#include <QTcpSocket>
#include <QSettings>
#include <QDateTime>

Client::Client(QString ipAddress, int port, QObject *parent):
QObject(parent), mTcpSocket(0), mIpAddress(ipAddress), mPort(port)
{
mTcpSocket = new QTcpSocket(this);
connect(mTcpSocket, SIGNAL(readyRead()),
this, SLOT(readSlot()));
connect(mTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(displayErrorSlot(QAbstractSocket::SocketError)));

std::cout << "Connecting to ip: " << mIpAddress.toStdString() << " port: " << mPort << std::endl;
mTcpSocket->connectToHost(mIpAddress, mPort);
}

void Client::readSlot()
{
static qint64 starttime = QDateTime::currentMSecsSinceEpoch();
static int frames = 0;

//know that the image is this big
int width = 800;
int height = 600;
int nChannels = 3;
int depth = 8;
qint64 blockSize = 1440000; //in bytes

if (mTcpSocket->bytesAvailable() < blockSize)
{
return;
}
frames++;

char* data = (char*) malloc(blockSize+100);
qint64 bytesRead = mTcpSocket->read(data, blockSize);

free(data);

//FPS
if(frames % 100 == 0){
float fps = frames/(QDateTime::currentMSecsSinceEpoch() - starttime);
std::cout << "FPS: " << fps << std::endl;
}
}

void Client::displayErrorSlot(QAbstractSocket::SocketError socketError)
{
switch (socketError) {
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
std::cout << "The host was not found. Please check the "
"host name and port settings."<< std::endl;
break;
case QAbstractSocket::ConnectionRefusedError:
std::cout << "The connection was refused by the peer. "
"Make sure the fortune server is running, "
"and check that the host name and port "
"settings are correct."<< std::endl;
break;
default:
std::cout << "The following error occurred: " << mTcpSocket->errorString().toStdString() << std::endl;
break;
}
}

最佳答案

  1. 您算错了帧数。您必须在 mTcpSocket->bytesAvailable() < blockSize 之后增加帧计数器测试!这就是你的非问题的根源:它工作正常,但你错误地计算了帧数。这也是它在 Linux 上“工作得更好”的原因:那里的网络堆栈以不同的方式缓冲数据,给你的信号更少。

  2. 您必须限制服务器端在线(缓冲)的内存量。否则,正如您正确注意到的那样,您将耗尽内存。看我的other answer有关如何操作的示例。

  3. 你永远不会释放你的内存malloc()在接收器中。请注意,如果服务器确实以 40 毫秒的间隔发送,则您应该期望每秒消耗 35 兆字节的 RAM。接收器很可能很快就会因内存泄漏而陷入困境。这可能是问题的根源。

  4. 那是什么QDataStream为了?您没有使用数据流来发送图像,并且在接收端也没有用处。

关于c++ - 在 Windows 7 上通过 QTcpSocket 流式传输图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11081005/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com