QTcpSocket に基づいて 2 つのテスト アプリケーションを作成しようとしています。これは、(圧縮されていない) 画像をストリーミングするサーバーと、それらを受信するクライアントです。
私のコードは主に Qts Fortune Client Example およびFortune Server Exampleから取られています。私はすべてのグイを切り取った。接続を開いて幸運を送信してからすぐに閉じる代わりに、サーバーは接続を開いたままにし、画像を継続的にストリーミングします。クライアントは QTcpSocket からイメージを読み取り、破棄します。
私が送信している画像は 800x600 RGB (=1440000 バイト) で、許可されている限り送信しています。画像は送信されるたびにファイルから読み取られ、圧縮は使用していません。
サーバーは画像を送信しているようです。しかし、クライアントは1秒あたり1〜4フレームとゆっくりと受信し、時々データを受信していないように見えるため、サーバーが大量のメモリを使用する原因になります(クライアントがサーバーが書き込み中です)。
サーバーとクライアントを異なるマシンで実行してみましたが、両方を 1 つのマシンで実行しましたが、どちらのセットアップでも同じ問題が発生します。
私のアプリケーションを Linux マシンで実行すると、クライアントははるかに高い速度で画像を受信します (1 秒あたり 14 フレームだったと考えてください)。クライアントは、サーバーが書き込むのと同じ速さで読み取ることができるようです。
この問題に光を当てるのを手伝ってくれる人はいますか?
- データ転送を高速化するにはどうすればよいですか? (圧縮を使用しない場合)
- サーバーが書き込んでいるのと同じ速さでクライアントを読み取らせるにはどうすればよいですか?
- これを Windows マシンで安定させるにはどうすればよいですか? (突然の一時停止はありません...) クライアントのコンソール ウィンドウをクリックすると、アプリケーションが「起動」しているように見えることがあります。^^
これが私のコードです:
サーバ:
main.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 );
}
クライアント:
main.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();
}
Client.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;
}
}