PDA

View Full Version : readLine problem



gQt
26th February 2008, 12:45
Hi,

I have a problem with the readLine function. It doesn't work while the computer is connected to the server. I have checked that the computer is connected with the telnet command. I have modified the Fortune Client example, removed the readFortune-function and added a readLine() in the requestNewFortune function. The last function is renamed to read_data(). I have also added a waitforConnected if test and a canReadLine if test before the readLine() and after the connectToHost. The canReadLine fails for some reason. I have also tried to remove the canReadLine but the readLine doesn't read anything (the output of mystring is empty). The program consists of three files: client.cpp, client.h, main.cpp

Any suggestions appreciated, thanks!

Regards
gQt


client.cpp


#include <QtGui>
#include <QtNetwork>
#include "client.h"
#include <iostream.h>
#include <QtCore>
#include <qdebug.h>
Client::Client(QWidget *parent)
: QDialog(parent)
{
hostLabel = new QLabel(tr("&Server name:"));
portLabel = new QLabel(tr("S&erver port:"));
hostLineEdit = new QLineEdit("10.249.0.48");
portLineEdit = new QLineEdit("4007");
portLineEdit->setValidator(new QIntValidator(1, 65535, this));

hostLabel->setBuddy(hostLineEdit);
portLabel->setBuddy(portLineEdit);
statusLabel = new QLabel(tr("This examples requires that you run the "
"Fortune Server example as well."));

getFortuneButton = new QPushButton(tr("Get Fortune"));
getFortuneButton->setDefault(true);
getFortuneButton->setEnabled(false);

quitButton = new QPushButton(tr("Quit"));

tcpSocket = new QTcpSocket(this);

connect(hostLineEdit, SIGNAL(textChanged(const QString &)),
this, SLOT(enableGetFortuneButton()));
connect(portLineEdit, SIGNAL(textChanged(const QString &)),
this, SLOT(enableGetFortuneButton()));
connect(getFortuneButton, SIGNAL(clicked()),
this, SLOT(read_data()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(read_data()));
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));

QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(1);
buttonLayout->addWidget(getFortuneButton);
buttonLayout->addWidget(quitButton);

QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(hostLabel, 0, 0);
mainLayout->addWidget(hostLineEdit, 0, 1);
mainLayout->addWidget(portLabel, 1, 0);
mainLayout->addWidget(portLineEdit, 1, 1);
mainLayout->addWidget(statusLabel, 2, 0, 1, 2);
mainLayout->addLayout(buttonLayout, 3, 0, 1, 2);
setLayout(mainLayout);

setWindowTitle(tr("Fortune Client"));
portLineEdit->setFocus();
}

void Client::read_data()
{
getFortuneButton->setEnabled(true);
tcpSocket->abort();
tcpSocket->connectToHost(hostLineEdit->text(),
portLineEdit->text().toInt());

cout << ("før if(canReadLine)\n");

if(tcpSocket->waitForConnected(-1))
{
cout <<"wait for connected loop";
if(tcpSocket->canReadLine())
{
tcpSocket->readLine();
qDebug() << "READ" << mystring;
cout <<"canReadLine loop";
}
statusLabel->setText(mystring);
getFortuneButton->setEnabled(false);
}

}
void Client::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError) {
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
QMessageBox::information(this, tr("Fortune Client"),
tr("The host was not found. Please check the "
"host name and port settings."));
break;
case QAbstractSocket::ConnectionRefusedError:
QMessageBox::information(this, tr("Fortune Client"),
tr("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."));
break;
default:
QMessageBox::information(this, tr("Fortune Client"),
tr("The following error occurred: %1.")
.arg(tcpSocket->errorString()));
}

getFortuneButton->setEnabled(true);
}

void Client::enableGetFortuneButton()
{
getFortuneButton->setEnabled(!hostLineEdit->text().isEmpty()
&& !portLineEdit->text().isEmpty());
}


client.h


#ifndef CLIENT_H
#define CLIENT_H
#include <QDialog>
#include <QTcpSocket>
#include <QAbstractSocket>

class QDialogButtonBox;
class QLabel;
class QLineEdit;
class QPushButton;
class QTcpSocket;
class Client : public QDialog
{
Q_OBJECT

public:
Client(QWidget *parent = 0);

private slots:
void read_data();
void displayError(QAbstractSocket::SocketError socketError);
void enableGetFortuneButton();

private:
QLabel *hostLabel;
QLabel *portLabel;
QLabel *cLabel;
QLineEdit *hostLineEdit;
QLineEdit *portLineEdit;
QLabel *statusLabel;
QPushButton *getFortuneButton;
QPushButton *quitButton;
QDialogButtonBox *buttonBox;

QTcpSocket *tcpSocket;
QTcpSocket tcpSocket2;
QString currentFortune;
QString mystring;
quint16 blockSize;

};

#endif


main.cpp


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

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Client client;
client.show();
return client.exec();
}

gQt
27th February 2008, 08:55
I forgot to say that the data I 'm trying to read with readLine looks like this:

$IIMWV,063,R,001.16,M,A*13
$IIMWV,042,R,002.66,M,A*14
$IIMWV,033,R,002.67,M,A*13
$IIMWV,041,R,001.71,M,A*12

with one new line available pr. second, so the problem can't be that readLine can't find a \n in the data. My problem is that the client connects, but readLine can't read anything.

Any help is deeply apreciated, thanks in advance!

Regards
gQt

wysota
27th February 2008, 09:17
The fact that there is a connection between two hosts doesn't yet mean there is anything to read and even if there is, it might not be terminated with a newline character(s).

gQt
27th February 2008, 12:13
Thanks for your reply!

I have tested that the data is available with the telnet command. The data comes with both LF and CR so canReadline /readLine should work. Output to terminal looks like this (changed all of the couts to english now)

function read_data()
after connectToHost
wait for connected loop
function read_data()
after connectToHost
wait for connected loop
function read_data()
after connectToHost
wait for connected loop
<Terminated with the Quit button>

<client.cpp>


#include <QtGui>
#include <QtNetwork>
#include "client.h"
#include <iostream.h>
#include <QtCore>
#include <qdebug.h>
Client::Client(QWidget *parent)
: QDialog(parent)
{
hostLabel = new QLabel(tr("&Server name:"));
portLabel = new QLabel(tr("S&erver port:"));
hostLineEdit = new QLineEdit("10.249.0.48");
portLineEdit = new QLineEdit("4002");
portLineEdit->setValidator(new QIntValidator(1, 65535, this));

hostLabel->setBuddy(hostLineEdit);
portLabel->setBuddy(portLineEdit);
statusLabel = new QLabel(tr("This examples requires that you run the "
"Fortune Server example as well."));

getFortuneButton = new QPushButton(tr("Get Fortune"));
getFortuneButton->setDefault(true);
getFortuneButton->setEnabled(false);

quitButton = new QPushButton(tr("Quit"));

tcpSocket = new QTcpSocket(this);

connect(hostLineEdit, SIGNAL(textChanged(const QString &)),
this, SLOT(enableGetFortuneButton()));
connect(portLineEdit, SIGNAL(textChanged(const QString &)),
this, SLOT(enableGetFortuneButton()));
connect(getFortuneButton, SIGNAL(clicked()),
this, SLOT(read_data()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(read_data()));
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));

QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(1);
buttonLayout->addWidget(getFortuneButton);
buttonLayout->addWidget(quitButton);

QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(hostLabel, 0, 0);
mainLayout->addWidget(hostLineEdit, 0, 1);
mainLayout->addWidget(portLabel, 1, 0);
mainLayout->addWidget(portLineEdit, 1, 1);
mainLayout->addWidget(statusLabel, 2, 0, 1, 2);
mainLayout->addLayout(buttonLayout, 3, 0, 1, 2);
setLayout(mainLayout);

setWindowTitle(tr("Fortune Client"));
portLineEdit->setFocus();
}

void Client::read_data()
{
getFortuneButton->setEnabled(true);
cout << "function read_data()\n";
tcpSocket->abort();
tcpSocket->connectToHost(hostLineEdit->text(),
portLineEdit->text().toInt());

cout << ("after connectToHost\n");

if(tcpSocket->waitForConnected(-1))
{
cout <<"wait for connected loop\n";
if(tcpSocket->canReadLine())
{
mystring=tcpSocket->readLine();
qDebug() << "READ" << mystring;
cout <<"canReadLine loop after readLine\n";
}
statusLabel->setText(mystring);
getFortuneButton->setEnabled(false);
}

}
void Client::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError) {
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
QMessageBox::information(this, tr("Fortune Client"),
tr("The host was not found. Please check the "
"host name and port settings."));
break;
case QAbstractSocket::ConnectionRefusedError:
QMessageBox::information(this, tr("Fortune Client"),
tr("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."));
break;
default:
QMessageBox::information(this, tr("Fortune Client"),
tr("The following error occurred: %1.")
.arg(tcpSocket->errorString()));
}

getFortuneButton->setEnabled(true);
}

void Client::enableGetFortuneButton()
{
getFortuneButton->setEnabled(!hostLineEdit->text().isEmpty()
&& !portLineEdit->text().isEmpty());
}

wysota
27th February 2008, 12:18
Thanks for your reply!

I have tested that the data is available with the telnet command. The data comes with both LF and CR so canReadline /readLine should work. Output to terminal looks like this (changed all of the couts to english now)

Does the output come to the terminal within a 1ns after establishing the connection? I doubt that... The data arrives, but it arrives later - you can't connect and expect the data to be already there.

gQt
27th February 2008, 13:00
I'm doing an if (waitForConnected(-1)) after the connectToHost if that wat you mean?

Should I add anything else here?
(I'm new to Qt and Socket-programming)

From the read_data() function:



tcpSocket->abort();
tcpSocket->connectToHost(hostLineEdit->text(),
portLineEdit->text().toInt());

cout << ("after connectToHost\n");

if(tcpSocket->waitForConnected(-1))
{
cout <<"wait for connected loop\n";
if(tcpSocket->canReadLine())
{
mystring=tcpSocket->readLine();
qDebug() << "READ" << mystring;
cout <<"canReadLine loop after readLine\n";
}
statusLabel->setText(mystring);
getFortuneButton->setEnabled(false);
}

wysota
27th February 2008, 13:37
I'm doing an if (waitForConnected(-1)) after the connectToHost if that wat you mean?
No, this waits for the connection to be established, not for the data to be ready.


Should I add anything else here?
QAbstractSocket::waitForReadyRead

(I'm new to Qt and Socket-programming)
That should motivate you to do some more reading.

gQt
27th February 2008, 14:23
Thanks a mill wysota :D!
I hadn't thought about the waitForReadyRead- that I had to wait for the data to be ready to read also.

wysota
27th February 2008, 14:30
Be aware that the fact that waitForReadyRead returns means there is something to read, not that everything is ready to be read.

gQt
29th February 2008, 08:09
sorry for postin the start of the thread again,

I have added a while waitForReadyRead loop inside the if waitForConnected and now it works.



void Client::read_data()
{
getFortuneButton->setEnabled(true);
//cout << "function read_data()\n";
tcpSocket->abort();
tcpSocket->connectToHost(hostLineEdit->text(),
portLineEdit->text().toInt());

//cout << ("after connectToHost\n");

if(tcpSocket->waitForConnected(-1))
{
//cout <<"wait for connected loop\n";

while(tcpSocket->waitForReadyRead(-1))
{
while(tcpSocket->canReadLine())
{
mystring=tcpSocket->readLine();
qDebug() << mystring;
statusLabel->setText(mystring);
}
getFortuneButton->setEnabled(false);
}


}

}

wysota
29th February 2008, 09:35
I still don't see you use waitForReadyRead...


x->connectToHost(...);
x->waitForConnected(...);
while(x->waitForReadyRead(10000)){
x->readAll(); // or canReadLine && readLine...
}