PDA

View Full Version : Trouble Applying the Fortune Threaded Server



dhice
11th April 2009, 23:27
I'm trying to integrate a QTcpServer into my program. My initial attempt was to use the Fortune client to connect to my server, and my server return a simple string. I'm not sure why, but the Fortune client will not connect.

I'm running both my program and the Fortune Client on my computer, using a connection address of Localhost and port 1000.

Here is my code:

Server.h

#ifndef SERVER_H
#define SERVER_H
#include <QTcpServer>
class Server : public QTcpServer
{
Q_OBJECT

public:
Server(QObject *parent = 0);

protected slots :
void incomingConnection(int socketDescriptor);

};

#endif // SERVER_H

Server.cpp


#include "Server.h"
#include "ServerThread.h"
#include <QDebug>


Server::Server(QObject *parent)
: QTcpServer(parent)
{
connect(this, SIGNAL(newConnection()), this, SLOT(incommingConnection(socketDescriptor)));
}

void Server::incomingConnection(int socketDescriptor)
{
qDebug() << "Incomming!";
QString fortune = "Test";
ServerThread *thread = new simonServerThread(socketDescriptor, fortune, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}


ServerThread.h



#ifndef SERVERTHREAD_H
#define SERVERTHREAD_H

#include <QThread>
#include <QTcpSocket>

class ServerThread : public QThread
{
Q_OBJECT

public:
ServerThread(int socketDescriptor, const QString &fortune, QObject *parent);

void run();

signals:
void error(QTcpSocket::SocketError socketError);

private:
int socketDescriptor;
QString text;
};


#endif // SERVERTHREAD_H


ServerThread.cpp



#include "ServerThread.h"

ServerThread::ServerThread(int socketDescriptor, const QString &fortune, QObject *parent)
: QThread(parent), socketDescriptor(socketDescriptor), text(fortune)
{
}

void ServerThread::run()
{
QTcpSocket tcpSocket;
if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
emit error(tcpSocket.error());
return;
}

QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint16)0;
out << text;
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));

tcpSocket.write(block);
tcpSocket.disconnectFromHost();
tcpSocket.waitForDisconnected();
}



I'm calling the server using the following:



Server server;
if (!server.listen(QHostAddress::Any, 1000)) {
QMessageBox::critical(this, tr("Threaded Fortune Server"),
tr("Unable to start the server: %1.")
.arg(server.errorString()));
server.close();
}

Thanks for trying to help!

wysota
11th April 2009, 23:35
Did you start the event loop in the main thread?

dhice
12th April 2009, 00:33
Yes the GUI event loop has been started.

wysota
12th April 2009, 07:31
Try connecting to the server with a telnet client and see if you can connect at all. And also try a higher port - ones between 1 and 1024 are reserved for well-known services and (may) require superuser privileges.

dhice
12th April 2009, 14:33
I changed the port number to 5000 with out any luck.

I then attempted telneting using this command


telnet localhost 5000

And it couldn't connect. The connection will go through if I omit the port number, so the telnet service is on.

wysota
14th April 2009, 21:20
What exactly message did you get when trying to connect to the port using telnet? "Connection refused" or something like "Connection closed by remote host"?

dhice
17th April 2009, 20:58
OK, I have the server working correctly now, as I can send/receive data between the server embedded in my program to a small client I created for testing purposes. Now I'm having trouble getting readyRead() to emit on the client side.

I modeled the embedded client code after the small client I made directly.

Here is my updated code.

client.h

#ifndef CLIENT_H
#define CLIENT_H
#include <QtGui/QDialog>
#include <QtNetwork>
#include <QVector>


class client : public QObject
{
Q_OBJECT

public:
client();
~client();
QString hostname;
QVector<int> sequence;
int state;
int ready;
void requestData();
QTcpSocket* socket;
void readData();

private:


private slots:

void readyReadTest();

signals:
void dataComplete();
};

#endif // CLIENT_H


client.cpp


#include "client.h"
#include <QDebug>

client::client()
{
qDebug() << "CLIENT>> \"Client Initialized\"";
ready = 0;
}

client::~client()
{

}


void client::requestData(){

socket = new QTcpSocket(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(readyReadTest()));
connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
qDebug() << "CLIENT>> CONNECTING TO \"" << hostname << ":5000\"";
QHostAddress address;
address.setAddress(hostname);
socket->connectToHost(address, 5000);
if(socket->isValid()){
qDebug() << "CLIENT>> CONNECTED TO: \""<<hostname << ":5000\"";
}
else{
qDebug() << "CLIENT>> FAILED TO CONNECTED TO: \""<<hostname << ":5000\"";
}
}

void client::readData(){
qDebug() << "CLIENT>> ATTEMPTING TO RECEIVE DATA";
int z = sequence.size();
sequence.clear();
QDataStream in(socket);
in.setVersion(QDataStream::Qt_4_1);
QString msg;
in >> msg;
qDebug() << "CLIENT>> MSG " << msg;
if(msg == ""){
qDebug() << "CLIENT>> MSG WAS NOT RECEIVED";
}
else{
qDebug() << "CLIENT>> MSG RECEIVED";
}
delete socket;
emit dataComplete();
}

void client::readyReadTest(){
qDebug() << "CLIENT>> READYREAD WAS EMITTED";
}


server.h


#ifndef SERVER_H
#define SERVER_H

#include <QtNetwork>

class server : public QTcpServer{
Q_OBJECT
public:
server(QObject* parent = 0);
QVector<int> *sequence;
int checkIn;
int state;

protected slots:
void sendMessage();
void connectCheck();
};

#endif // SERVER_H


server.cpp


#include "server.h"
#include <QDebug>

server::server(QObject* parent) : QTcpServer(parent) {
qDebug() << "SERVER>> \"Server Intialized\"";
connect(this, SIGNAL(newConnection()), this, SLOT(sendMessage()));
}

void server::sendMessage(){
qDebug() << "SERVER>> PREPARING TO SEND DATA";
QString message;
QTcpSocket* client = this->nextPendingConnection();
QByteArray block;
QDataStream outgoingMessage(&block, QIODevice::WriteOnly);
outgoingMessage.setVersion(QDataStream::Qt_4_1);
int i = 0;
qDebug() << "SERVER>> SEQUENCE SIZE " << (*sequence).size();
for(i; i < (*sequence).size();i++){
message = QString::number((*sequence)[i]);
qDebug() << "SERVER>> SENDING\"" << message << "\"";
outgoingMessage << message;
}
client->write(block);
client->disconnectFromHost();
}



How I'm calling the server/client


if(player == 1){
qDebug() << "ENGINE>> GENERATING NEXT NUMBER";
generate_number();
SERVER->sequence = &sequence_computer;
}
else{
client CLIENT;
CLIENT.hostname = hostname;
while(sequence_computer.size() == 0){
CLIENT.requestData();
sequence_computer = CLIENT.sequence;
qDebug() << "ENGINE>> WAITING FOR CLIENT TO RECEIVE SEQUENCE";
msleep(1000);
}
}

I do have a few unused variables in the header files (debugging and haven't removed them yet)

Thanks for any help to understand why readyRead() isn't firing.

wysota
18th April 2009, 22:04
Because there is nothing written to the socket. You are disconnecting the server from the client before the data has a chance to be written. You need to wait for bytesWritten before calling disconnectFromHost.