PDA

View Full Version : QVector of pointers to custom classes that contain sockets



Gadgetman53
10th April 2011, 01:02
I have two custom classes (shown below) that I am trying to use in order to have multiple connections to a server(s). These connections are to what is called APRS-IS servers, they way it works is, I connect to the server and send an authorization string, after I am authenticated the server sends me APRS "packets" as text across the socket as they come to the server that I am connected to. I know that my ServerConnection class (below) works for this purpose (individually), but I want to be connected to multiple ports of the server (representing different types of packets). So for that purpose I have a ConnectionInterface class (below), it has a QVector of pointers to the ServerConnection Objects.

My problem is:

I can create a ConnectionInterface object, I then use the newConnection method to create a new ServerConnection object and append that to the QVector

I then connect to the server using the pointer to that ServerConnection and calling the ServerConnection::connectToServer() method. My problem is, no matter how many ServerConnections I have in the QVector when I call the connectToServer method, it seems to stay connected to whatever connection I call last:

for instance, I call ConnectionInterface::connectToServer(0) //where 0 represents the index in the QVector of the ServerConnection object I want it to connect.

I then can call connectToServer(1) and the server only shows I am connected on the port that the ServerConnection at index 1 represented.

I appologize for the long explanation, but I didn't know any other way to state my problem. Any help would be GREATLY appreciated!

Here is my code - sorry for triple-post

ServerConnection.h


#ifndef SERVERCONNECTION_H
#define SERVERCONNECTION_H

#include <QTcpSocket>
#include <QApplication>

class ServerConnection : public QObject
{
Q_OBJECT

public:
// Parameterized constructor
ServerConnection(QString name, QString host, int port, QString authName, QString password, QString filterString);
ServerConnection(QString name, QString host, int port, QString authName, QString password, QString filterString, bool writeEnabled);
~ServerConnection(); // Deconstructor
private:
QTcpSocket* socket; // Pointer to a QTcpSocket that will be this instance's connection
QString name; // Name of this connection
QString host; // Hostname that this connection will be established to
int port; // Port number of the host that this connection will connect to
QString authName; // Login name for the server that this will connect to
QString password; // Password for the login name of the server this will connect to
QString authString; // The authentication string used to connect to the server
QString filterString; // The filter string entered by user in order to filter via server
bool writeEnabled; // Lets this instance know if it can write to the connection or not
bool connected; // Connected to server?
public:
QString getPacket(); // Gets packet that is waiting
void connectToServer(); // Connect to the server using name, host, port, authname, password attributes given during object creation
void disconnectFromServer(); // Disconnect from the currently connected server
QString getName(); // Returns the name given to this connection
QString getHostName(); // Returns the hostname of the server that this object connects to
int getPortNumber(); // Returns the port number used to connect
QString getUserName(); // Returns the username used to log onto server
QString getPassword(); // Returns the password associated with the username used to log onto the server
QString getFilterString(); // Returns the filter string that was set for this server
bool isWriteEnabled(); // Is this instance able to write to socket?
void setWriteEnabled(bool writeEnabled); // Sets if this socket can be written to

// change any parameters of this connection
void changeParameters(QString name, QString host, int port, QString authName, QString password, QString filterString);
void writeToSocket(QString aprsPacket); // writes the packet that is sent to this connection
bool isConnected(); // Connected to server??
signals:
void newData(QString); // Sends the latest packet to the controller object
private slots:
void newDataFromConnection(); // receives data from connection and emits newData
};

#endif // SERVERCONNECTION_H


ServerConnection.cpp


#include "serverconnection.h"

// Creates and returns an object of ServerConnection type that has attributes that are passed to it via parameters
ServerConnection::ServerConnection(QString name, QString host, int port, QString authName, QString password, QString filterString)
{
// The below 6 lines set the attributes of this object to those given to the constructor via parameters
this->name = name;
this->host = host;
this->port = port;
this->authName = authName;
this->password = password;
this->filterString = filterString;
connected = false; // Not connected to server
socket = new QTcpSocket(this); // Create a new QTcpSocket
socket->setObjectName(name);

// Set up the authentication string
authString = "user " + authName + " pass " + password + " vers QTAPRS v1 " + filterString + "\n";
connect(socket, SIGNAL(readyRead()), this, SLOT(newDataFromConnection())); // Connect this socket's readyread signal to slot
}

ServerConnection::ServerConnection(QString name, QString host, int port, QString authName, QString password, QString filterString, bool writeEnabled)
{
// The below 6 lines set the attributes of this object to those given to the constructor via parameters
this->name = name;
this->host = host;
this->port = port;
this->authName = authName;
this->password = password;
this->filterString = filterString;
this->writeEnabled = writeEnabled;
connected = false; // Not connected to server
socket = new QTcpSocket(this); // Create a new QTcpSocket
socket->setObjectName(name);

// Set up the authentication string
authString = "user " + authName + " pass " + password + " vers QTAPRS v1 " + filterString + "\n";
connect(socket, SIGNAL(readyRead()), this, SLOT(newDataFromConnection())); // Connect this socket's readyread signal to slot
}

// Deletes the connection and takes care of all of the logistical stuff
ServerConnection::~ServerConnection()
{
disconnectFromServer(); // disconnect socket from server
delete socket; // delete socket
}

// Forms a connection to the server that this object represents
void ServerConnection::connectToServer()
{
socket->connectToHost(host,port,QAbstractSocket::ReadWrite );// connects to host
socket->waitForConnected(30000); // Make sure we're connected (get rid of latency)
qDebug() << "Socket State = " << socket->state();

if(socket->state() != QAbstractSocket::ConnectedState){
QApplication::beep(); // We are not connected, beep to warn user
qDebug() << "NOT CONNECTED!!\n";
}
else{// we are connected
connected = true; // socket is connected
qDebug() << "Authentication String = " << authString;
authString.append("\n");
writeToSocket(authString); // Send server authentication string
qDebug() << "AuthString written to socket\n";
}
}


// disconnect from the server this object represents
void ServerConnection::disconnectFromServer()
{
connected = false; // socket is not connected
socket->disconnect(); // disconnect from server
socket->close(); // close socket
}

// Change the attributes of this connection
void ServerConnection::changeParameters(QString name, QString host, int port, QString authName, QString password, QString filterString)
{ // Change this objects local attributes
this->name = name;
this->host = host;
this->port = port;
this->authName = authName;
this->password = password;
this->filterString = filterString;
socket->setObjectName(name);
}

// Write aprsPacket (given as parameter) to the socket
void ServerConnection::writeToSocket(QString aprsPacket)
{
QByteArray block = aprsPacket.toAscii(); // allocate a bytearray to send aprsPacket with
socket->write(block); // write block to socket
qDebug() << "Wrote { " + aprsPacket + " } to server " + this->host + "\n";
}

// new packet has been received by connection
void ServerConnection::newDataFromConnection()
{
emit this->newData(getPacket()); // emit the packet to whomever cares
//qDebug() << "newData() emitted\n";
}

// returns the QString form of the packet received from the server
QString ServerConnection::getPacket()
{
char buf[1024]; // Create a buffer of type char to hold packet
memset(buf,0,1024); // Zeros out memory that buffer is located at
socket->read(buf,1024); // reads data from socket and stores to buf
QString string(buf); // casts the char buffer to a string
//qDebug() << string.toUtf8();
return string.toUtf8(); // returns the string that represents packet
}

// is this object currently connected to a server?
bool ServerConnection::isConnected()
{
return this->connected; // returns true if connected or false if not connected
}

// Returns the name given to this connection
QString ServerConnection::getName()
{
return this->name;
}

// Returns the hostname of this connection
QString ServerConnection::getHostName()
{
return this->host;
}

// Returns the port that this connection uses
int ServerConnection::getPortNumber()
{
return this->port;
}

// Returns the username used to authenticate with server
QString ServerConnection::getUserName()
{
return this->authName;
}

// Returns password used to authenticate with server
QString ServerConnection::getPassword()
{
return this->password;
}

// Returns the filterstring used to do server-side filtering of aprs data
QString ServerConnection::getFilterString()
{
return this->filterString;
}

bool ServerConnection::isWriteEnabled()
{
return this->writeEnabled;
}


ConnectionInterface.h



#ifndef CONNECTIONINTERFACE_H
#define CONNECTIONINTERFACE_H

#include <serverconnection.h>
#include <QVector>

class ConnectionInterface : public QObject
{
Q_OBJECT

public:
ConnectionInterface(); // constructor
~ConnectionInterface(); // deconstructor

// Creates a new connection and returns true if connection was made, false if not
bool newConnection(QString name, QString host, int port, QString authName, QString password, QString filterString, bool writeEnabled);
private:
int _numConnections; // The total number of connections QVector::size()
QVector<ServerConnection*> _connections; // QVector containing pointers to connection objects
public:
void connectToServer(int connectionID); // Connect to the server represented by connection connectionID
void disconnectFromServer(int connectionID); // disconnect from the server represented by connection connectionID

// Change any of the parameters of the connection represented by connection connectionID
void changeParameters(QString name, QString host, int port, QString authName, QString password, QString filterString, int connectionID);
void writeToSocket(QString aprsPacket); // Write the packet aprsPacket to connection to server represented by connection connectionID
bool isConnected(int connectionID); // Tests if the connection represented by connection connectionID is connected
QString getName(int connectionID); // Returns the name given to this connection
QString getHostName(int connectionID); // Returns the hostname of the server that this object connects to
int getPortNumber(int connectionID()); // Returns the port number used to connect
QString getUserName(int connectionID); // Returns the username used to log onto server
QString getPassword(int connectionID); // Returns the password associated with the username used to log onto the server
QString getFilterString(int connectionID); // Returns the filter string that was set for this server
void deleteConnection(int connectionID);
public slots:
void getData(QString data); // Slot that catches all emitted signals
signals:
void newData(QString); // emitted containing new packet
};

#endif // CONNECTIONINTERFACE_H


ConnectionInteface.cpp


#include "connectioninterface.h"

ConnectionInterface::ConnectionInterface()
{
_numConnections = _connections.size(); // Set _numConnections to size of connection vector
}

ConnectionInterface::~ConnectionInterface()
{
qDeleteAll(_connections.begin(), _connections.end()); // Delete all objects pointed to in the vector
_connections.clear(); // Clear the pointers in the vector
}

void ConnectionInterface::connectToServer(int connectionID)
{
if(_connections.size() > connectionID)
{
if(!_connections[connectionID]->isConnected())
{
_connections[connectionID]->connectToServer();
}
else
{
QApplication::beep();
}
}
else
{
QApplication::beep();
}
}

void ConnectionInterface::changeParameters(QString name, QString host, int port, QString authName, QString password, QString filterString, int connectionID)
{
if(_connections.size() > connectionID)
{
_connections[connectionID]->changeParameters(name,host,port,authName,password, filterString);
}
else
{
QApplication::beep();
}
}

void ConnectionInterface::disconnectFromServer(int connectionID)
{
if(_connections.size() > connectionID)
{
if(_connections[connectionID]->isConnected())
{
_connections[connectionID]->disconnectFromServer();
}
else
{
QApplication::beep();
}
}
else
{
QApplication::beep();
}
}

void ConnectionInterface::writeToSocket(QString aprsPacket)
{
for(int i = 0; i < _connections.size(); i++)
{
if(_connections[i]->isWriteEnabled())
{
_connections[i]->writeToSocket(aprsPacket);
}
}
}

bool ConnectionInterface::isConnected(int connectionID)
{
if(_connections.size() > connectionID)
{
if(_connections[connectionID]->isConnected())
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}

bool ConnectionInterface::newConnection(QString name, QString host, int port, QString authName, QString password, QString filterString, bool writeEnabled)
{
ServerConnection* connection = new ServerConnection(name,host,port,authName,password, filterString,writeEnabled); // Creates a new connection Object
connect(connection,SIGNAL(newData(QString)),this,S LOT(getData(QString))); // connects the signal emitted when a new packet is received on this connection
_connections.push_back(connection); // Add this new connection object to the _connections vector
}

void ConnectionInterface::getData(QString data)
{
qDebug() << data;
emit newData(data); // New packet from a connection
}


Thanks in advance for any information you can offer to help me fix this!

Gadgetman53

Gadgetman53
10th April 2011, 22:59
any ideas anyone??

Gadgetman53

Gadgetman53
12th April 2011, 05:01
Figured this one out.

For future reference to anyone having this issue, javaaprs (the server that runs and this project was to connect to) does not support multiple AUTHENTICATED instances of the same user.