PDA

View Full Version : QTcpSocket connection problem



valdemar593
27th May 2011, 16:37
Hello everyone. I'm trying to write a chat using QTcpSocket and QTcpServer, but strange things are happening. In the first example QTcpServer emits newConnection(), but QTcpSocket remains in connecting state without emiting error(...). In the second example I receive SIGSEGV when trying connectToHost() . What is more, FortuneClient/Server (single threaded) example runs just fine. In both examples network sessiong is not required. Being discouraged I examined the Fortune code and discovored that it is just the same concerning establishing connection. Here are both examples.

FIRST



//CLIENT
ChatClient::ChatClient(QObject *parent)
: QObject(parent) {
tcpSocket = new QTcpSocket(this);
QNetworkConfigurationManager manager;
if (QNetworkConfigurationManager::NetworkSessionRequi red
& manager.capabilities()) {
qDebug() << "Network session required";
}
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(error(QAbstractSocket::SocketError)));
connect(tcpSocket, SIGNAL(connected()),
this, SLOT(requestForID()));
connect(tcpSocket, SIGNAL(readyRead()),
this, SLOT(receiveMessage()));
tcpSocket->connectToHost("192.168.0.100", PORT);
}
...
void ChatClient::error(QAbstractSocket::SocketError error) {
qDebug() << "Socket error" << error;
}

void ChatClient::requestForID() {
qDebug() << "Connected, requesting for ID";
QByteArray segment;
QDataStream out(&segment, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_7);
out << (quint16)0 << ID;
out.device()->seek(0);
out << (quint16)(segment.size() - sizeof(quint16));
tcpSocket->write(segment);
}

//SERVER
ChatServer::ChatServer(QObject *parent)
: QObject(parent) {
tcpServer = new QTcpServer(this);
if (!tcpServer->listen(/*QHostAddress::Any, PORT*/)) {
qDebug() << "Unable to start the server"
<< tcpServer->errorString();
}
qDebug() << "Server port" << tcpServer->serverPort();
connect(tcpServer, SIGNAL(newConnection()),
this, SLOT(processConnection()));
}

void ChatServer::processConnection() {
qDebug() << "Incoming connection";
QTcpSocket *clientSocket = tcpServer->nextPendingConnection();
/*connect(clientSocket, SIGNAL(readyRead()),
this, SLOT(readData()));
readData(clientSocket);
connect(clientSocket, SIGNAL(disconnected()),
clientSocket, SLOT(deleteLater()));*/
QByteArray segment;
QDataStream out(&segment, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_7);
out << (quint16)0 << (quint16)Message
<< "Successfully connected";
out.device()->seek(0);
out << (quint16)(segment.size() - sizeof(quint16));
clientSocket->write(segment);
clientSocket->disconnectFromHost();
}


SECOND



//CLIENT
Client::Client() {
QTcpSocket *clientSocket = new QTcpSocket(this);
connect(clientSocket, SIGNAL(connected()),
this, SLOT(connectionEstablished()));
connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(error()));
}

void Client::establishConnection() {
// throws SIGSEGV
clientSocket->connectToHost(QHostAddress("192.168.0.100"), 6178);
}

void Client::connectionEstablished() {
qDebug() << "Connection established";
}

void Client::error() {
qDebug() << clientSocket->errorString();
}

//SERVER
Server::Server() {
QNetworkConfigurationManager manager;
if (manager.capabilities() &
QNetworkConfigurationManager::NetworkSessionRequir ed) {
qDebug() << "Network session required";
} else {
sessionOpened();
}
connect(server, SIGNAL(newConnection()),
this, SLOT(processConnection()));
}

void Server::processConnection() {
qDebug() << "Incoming connection";
}

void Server::sessionOpened() {
server = new QTcpServer(this);
if (!server->listen(QHostAddress::Any, 6178)) {
qDebug() << QString("Unable to start the server: %1")
.arg(server->errorString());
return;
}
qDebug() << "The server is running...";
}


Any ideas?

kosasker
27th May 2011, 16:42
Use QThread and Mutex. I solved with them. I want to send it but my code is C based.

valdemar593
27th May 2011, 16:50
Please explain why I should use QMutex and QThread in those examples? Should I implement tcp connection in a seperate thread?

kosasker
27th May 2011, 16:57
Oh.. its just my opinion :)
No not. Just inherit your class from QThread like this



class logthread : public QThread
{
Q_OBJECT
public:
explicit logthread(QObject *parent = 0);
~logthread();
..........


and use mutex only when your application sends data



QMutex mutex;
...........
.........
.........
mutex.lock();
send_function();
mutex.unlock();


Its a very basic example but my code is running clearly. For more information just read the docs.

valdemar593
27th May 2011, 16:59
Thanks I'll try right now. Should I lock tcpSocket->connectToHost()? But why FortuneClient/Server doesn't use mutex and doesn't inherit QThread and works fine?

wysota
27th May 2011, 17:05
There is no reason to use threads and mutexes here.

valdemar593
27th May 2011, 17:10
Yes that hasn't solved the problem. But still I'm confused because Fortune example works and my doesn't. At the same time I do not find differencies except that Fortune iterates over network interfaces to choose one and I choose manually. Even then both IP addresses are the same. May be I should post the full code? It is not long.

wysota
27th May 2011, 17:13
Post the debugger backtrace after a crash.

valdemar593
27th May 2011, 17:18
//
int idx = obj->metaObject()->indexOfMethod(sig.constData());
//
return invokeMethod(obj, member, type, QGenericReturnArgument(), val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
//
QMetaObject::invokeMethod(this, "connectToHostImplementation",
Qt:: DirectConnection,
Q_ARG(QString, hostName),
Q_ARG(quint16, port),
Q_ARG(OpenMode, openMode));
//
connectToHost(address.toString(), port, openMode);
//
clientSocket->connectToHost(QHostAddress("192.168.0.100"), 6178);

please note that I talk about two different projets, where in the first one QTcpSocket remains in connecting state while in the second QTcpSocket::connectToHost() produces SIGSEGV.

wysota
27th May 2011, 17:47
Please post the backtrace as requested.

valdemar593
27th May 2011, 17:52
Sorry I misunderstand what is backtrace?

wysota
27th May 2011, 17:53
http://en.wikipedia.org/wiki/Call_stack

If you are using Qt Creator, the backtrace is in the "stack" view when you're in the Debug mode.

valdemar593
27th May 2011, 17:55
gdb

#0 0x00402b73 in QMetaObject::invokeMethod (obj=0x7e9ff4,
member=0x22a33f "connectToHostImplementation", type=Qt::DirectConnection,
ret=..., val0=..., val1=..., val2=..., val3=..., val4=..., val5=..., val6=...,
val7=..., val8=..., val9=...)
at /var/tmp/qt-src/src/corelib/kernel/qmetaobject.cpp:1135
#1 0x001efe73 in invokeMethod (this=0x7e9ff4, hostName=..., port=6178, openMode=...)
at ../../include/QtCore/../../src/corelib/kernel/qobjectdefs.h:408
#2 QAbstractSocket::connectToHost (this=0x7e9ff4, hostName=..., port=6178,
openMode=...) at /var/tmp/qt-src/src/network/socket/qabstractsocket.cpp:1304
#3 0x001f1835 in QAbstractSocket::connectToHost (this=0x7e9ff4, address=...,
port=6178, openMode=...)
at /var/tmp/qt-src/src/network/socket/qabstractsocket.cpp:1417
#4 0x080494e4 in Client::establishConnection (this=0xbffff1fc)
at ../NetTestClient/client.cpp:13
#5 0x08049201 in main (argc=1, argv=0xbffff2d4) at ../NetTestClient/main.cpp:8

qt creator

0 QHashData::detach_helper2 qhash.cpp 206 0x001a18fa
1 QHash<QObject*, QHash<QEvent::Type, int> >::detach_helper qhash.h 582 0x002e69eb
2 detach qhash.h 299 0x002dbc23
3 operator[] qhash.h 737 0x002dbc23
4 QStateMachinePrivate::registerEventTransition qstatemachine.cpp 1598 0x002dbc23
5 invokeMethod qobjectdefs.h 408 0x00a25e73
6 QAbstractSocket::connectToHost qabstractsocket.cpp 1304 0x00a25e73
7 QAbstractSocket::connectToHost qabstractsocket.cpp 1417 0x00a27835
8 Client::establishConnection client.cpp 13 0x080494e4
9 main main.cpp 8 0x08049201

:D

wysota
27th May 2011, 18:14
What does the main() function look like?

valdemar593
27th May 2011, 18:22
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Client client;
client.establishConnection();
return a.exec();
}

wysota
27th May 2011, 18:49
Ah.... I missed it. You are creating a local variable called "clientSocket" in your constructor that shadows the class member called "clientSocket" thus it remains uninitialized and a dangling pointer causes a crash.

valdemar593
27th May 2011, 19:10
Oh my god =))
Thanks a lot man!
But what about the first example? Everything seems to be correct there, but the socket stays in connecting state all the time while the server emits newConnection()?

wysota
27th May 2011, 19:13
I don't know, I'd need to see code that's more complete than this.