PDA

View Full Version : Send Image over TCP failed ??



ganapathi
30th November 2015, 06:21
Hi,

I am trying to send the image(768*1024) block by block ie, 768*20 blocks or more specifically stripe by stripe.

The client sends such stripes of image and server displays the image.

Here is the client code:

client_image.h



#ifndef CLIENT_IMAGE_H
#define CLIENT_IMAGE_H

#include <QObject>
#include <QLabel>
#include <QImage>
#include <QObject>
#include <QThread>
#include <QtNetwork/QTcpSocket>
#include <QDebug>
#include <QPixmap>


class Client_Image:public QObject

{
Q_OBJECT
public:
Client_Image();
signals:
void done();

private slots:
void broadcastLine();

private:
QTcpSocket *socket;
QImage *image;
quint16 a;
quint16 img_block;
quint8 block_size;

};

#endif // CLIENT_IMAGE_H





Client_Image Source Code ::::





#include "client_image.h"
#include <QDebug>
#include <QObject>
#include <QImage>
#include <QTimer>
#include <QByteArray>
#include <QDataStream>




Client_Image::Client_Image()
{

socket = new QTcpSocket(this);
a = 0;
img_block = 0;
block_size = 20;

socket->connectToHost("127.0.0.1",1234);

image = new QImage("C:/Users/Public/Pictures/Sample Pictures/Desert.jpg" );

if( image->isNull() )
qDebug() << )"Failed to open test.jpg" ;
else
qDebug() << "Opened the test.jpg" ;

QTimer *timer = new QTimer(this );
timer->isSingleShot();
QTimer::singleShot(1000, this, SLOT(broadcastLine()) );
connect( this, SIGNAL(done()), this, SLOT(broadcastLine()) );

}

void Client_Image::broadcastLine()
{

QByteArray buffer( block_size+3*image->width(), 0 );
QDataStream stream( &buffer, QIODevice::WriteOnly );
stream.setVersion( QDataStream::Qt_5_5 );

stream << (quint16)image->width() << (quint16)image->height();


stream << img_block;


for( int x=0; x<image->width(); ++x )
{
for(int y=block_size*a; y <block_size+(block_size*a);y++)
{
if( y < image->height())
{
QRgb rgb = image->pixel( x, y );
stream << (quint8)qRed( rgb ) << (quint8)qGreen( rgb ) << (quint8)qBlue( rgb );
}
else
{
y = a = 0;
img_block = -block_size;
}
}
}


socket->write(buffer);
qDebug() << buffer.size() << "buffer size";

socket->waitForBytesWritten(10);
socket->flush();
img_block = img_block + block_size;
a++;

emit done();

}








Server Side Code used for Image display

Xrayserver.h




#ifndef XRAYSERVER_H
#define XRAYSERVER_H

#include <QObject>
#include <QTcpServer>
#include "clientsocket.h"
class XRayServer : public QTcpServer
{
Q_OBJECT

public:

explicit XRayServer(QObject *parent = 0);
void startServer();

signals:


public slots:


protected:
void incomingConnection(qintptr socketDescriptor);


};

#endif // XRAYSERVER_H




Xrayserver.cpp



#include "xrayserver.h"
//#inlcude "clientsocket.h"
#include<QThread>


XRayServer::XRayServer(QObject *parent) : QTcpServer(parent)
{

}

void XRayServer::startServer()
{
int port = 1234;
if(!this->listen(QHostAddress::Any, port))
{
qDebug() << "Could not start server";
}
else
{
qDebug() << "Listening to port " << port << "...";
}
}


void XRayServer::incomingConnection(qintptr socketDescriptor)
{
// We have a new connection
qDebug() << socketDescriptor << " Connecting...";

QThread* client_thread = new QThread;
ClientSocket* client_socket = new ClientSocket(socketDescriptor);


}




One socket for each client connected to the server(Clientsocket.h and clientsocket.cpp files below)

ClientSocket.h



ClientSocket.h /// Header file

#ifndef CLIENTSOCKET_H
#define CLIENTSOCKET_H

#include <QLabel>
#include <QImage>
#include <QObject>
#include <QThread>
#include <QTcpSocket>
#include <QDebug>
#include <QPixmap>
#include <QHostAddress>
class ClientSocket : public QLabel
{
Q_OBJECT
public:
explicit ClientSocket(qintptr ID);

signals:
void error(QTcpSocket::SocketError socketerror);
public slots:
void readyRead();
void disconnected();
private:
QTcpSocket *socket;
qintptr socketDescriptor;
QImage *image;
quint8 block_size;
QHostAddress ipaddress;

};

#endif // CLIENTSOCKET_H


ClientSocket.cpp



#include "clientsocket.h"
#include <QImage>
#include <QPixmap>
#include <QtNetwork/QTcpSocket>
#include <QDataStream>

ClientSocket::ClientSocket(qintptr ID)
{

socketDescriptor = ID;
socket = new QTcpSocket();
image = 0;
block_size = 20;
setMinimumSize(768,1024);

if(!socket->setSocketDescriptor(this->socketDescriptor))
{

emit error(socket->error());
return;
}

QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
qDebug() << socketDescriptor << " Client connected";
ipaddress = socket->peerAddress();
qDebug() << ipaddress ;

}

void ClientSocket::readyRead()
{

QByteArray buffer = socket->readAll();
qDebug() << "socket read data\n";


QDataStream stream( buffer );
stream.setVersion( QDataStream::Qt_5_5 );
quint16 width, height, y;
stream >> height >> width >> y;
qDebug() << "crl1" << width << height;

qDebug() << "socket read data 1\n";


if( !image )
image = new QImage( width, height, QImage::Format_RGB32 );
else if( image->width() != width || image->height() != height )
{
delete image;
image = new QImage( width, height, QImage::Format_RGB32 );
}

qDebug() << "socket read data 2\n";

for( int x=0; x<width; ++x ) {
for( int z=y;z<y+block_size;z++){
quint8 red, green, blue;
stream >> red >> green >> blue;
image->setPixel( x, z, qRgb( red, green, blue ) );
}
}

qDebug() << "socket read data 3\n";

setPixmap( QPixmap::fromImage( *image ) );

resize( image->size() );

this->show();
}



void ClientSocket::disconnected()
{
qDebug() << socketDescriptor << " Disconnected";

socket->deleteLater();

}






The above method worked for UDP sockets but not working for TCP.


I know there is something wrong with socket->readAll() in void ClientSocket::readyRead() function in ClientSocket.cpp source file. But dont know how to correct it.

Regards

yeye_olive
30th November 2015, 10:22
You have not provided any details beyond "it does not work", so you will probably get vague answers.

Your TCP code suffers from the same problems as your UDP code, which I pointed out in your other thread: strange global variables such as "a" and "img_block" are being modified all over the place, the "y" counter in a for loop is modified inside the body of the loop, etc. Maybe you got it working on UDP, but I wonder how maintainable it is.

Here is one new problem in your TCP code: you seem to assume that after you call socket->write(buffer) in the client, the server receives all this data, and only it, as one nice block, which you can read with socket->readAll(). That is not how TCP works. I strongly suggest you read http://blog.stephencleary.com/2009/04/message-framing.html to understand the problem.

ganapathi
30th November 2015, 10:49
Your TCP code suffers from the same problems as your UDP code, which I pointed out in your other thread: strange global variables such as "a" and "img_block" are being modified all over the place, the "y" counter in a for loop is modified inside the body of the loop, etc. Maybe you got it working on UDP, but I wonder how maintainable it is.

Here is one new problem in your TCP code: you seem to assume that after you call socket->write(buffer) in the client, the server receives all this data, and only it, as one nice block, which you can read with socket->readAll(). That is not how TCP works. I strongly suggest you read http://blog.stephencleary.com/2009/04/message-framing.html to understand the problem.

My aim is only to test the concepts than optimize it. Just get it working.

I will go through that link and implement those solutions and let you know further .

Thanks a lot for the link.

^NyAw^
30th November 2015, 12:18
Hi,

As yeye_olive explained, you are assuming that the full image will be received in one slot call on the client side. This is not true, so you will receive the image into blocks(data chunks).



My aim is only to test the concepts than optimize it. Just get it working.


This is not a optimization problem, the problem is the concept.

Please, read the link that yeye_olive provided you.

ganapathi
2nd December 2015, 11:26
You have not provided any details beyond "it does not work", so you will probably get vague answers.

Your TCP code suffers from the same problems as your UDP code, which I pointed out in your other thread: strange global variables such as "a" and "img_block" are being modified all over the place, the "y" counter in a for loop is modified inside the body of the loop, etc. Maybe you got it working on UDP, but I wonder how maintainable it is.

Here is one new problem in your TCP code: you seem to assume that after you call socket->write(buffer) in the client, the server receives all this data, and only it, as one nice block, which you can read with socket->readAll(). That is not how TCP works. I strongly suggest you read http://blog.stephencleary.com/2009/04/message-framing.html to understand the problem.

Dear yeye_olive,

I implemented http://blog.stephencleary.com/2009/04/message-framing.html length prefixing solution and is working perfect. I will share the code once fully implemented.

Nothing is global. Server and Clent are in different classes and no sharing at all.
Regarding the y variable modification , I will check out once more.

Thanks Yeye