Problem mit QTcpServer/QTcpSocket

Alles rund um die Programmierung mit Qt
Antworten
rurseekatze
Beiträge: 7
Registriert: 15. Dezember 2009 17:03

Problem mit QTcpServer/QTcpSocket

Beitrag von rurseekatze »

Hallo,

ich will mir eine einfache Chatanwendung programmieren. Den Client habe ich soweit fertig gestellt und nun bin ich dabei, den Server zu schreiben. Allerdings habe ich folgendes Problem, und ich verstehe einfach nicht, warum es nicht klappen will:

Der Client kann sich erfolgreich mit dem Server verbinden, und der Server schickt "hello new client", was der Client auch empfängt. Bis "new client wants to connect and sended NEW" läuft auch alles ohne Probleme durch und die entsprechenden Meldungen erscheinen auch. Schicke ich nun mit dem Client etwas an den Server, wird readyRead() ausgelöst und "new client wants to connect and sended NEW" ausgegeben, der Client empfängt jedoch dann nichts und "c" wird nicht ausgegeben. Nehme ich das raus, hängt er beim Senden, wieder wird "c" nicht ausgegeben und der Client empfängt nichts.

Ich habe einfach keine Ahnung, wo der Fehler liegt, denn am Client liegt es anscheinend nicht und der Server kann auch versenden und das readyRead() Signal wird ausgelöst.


Hier noch der Code:
italk.cpp

Code: Alles auswählen

#include "italk.h"

italk::italk(QMainWindow *parent) : QMainWindow(parent)
{
	setupUi(this);
	connect(actionAbout, SIGNAL (triggered()), this, SLOT(showAbout()));
	connect(actionAboutQt, SIGNAL (triggered()), qApp, SLOT(aboutQt()));
	connectionStatusBar->showMessage(QString(tr("Nicht verbunden.")));
	setServerOnline();
}

italk::~italk()
{
}

void italk::setServerOnline()
{
	commandServer = new QTcpServer(this);
	commandServer->listen(QHostAddress::Any,51238);
	connect(commandServer, SIGNAL(newConnection()), this, SLOT(newClient()));
}

void italk::newClient()
{
	cout << "new client" << endl;
	if (commandServer->hasPendingConnections())
	{
		QTcpSocket *clientSocket = commandServer->nextPendingConnection();
		connect(clientSocket, SIGNAL(readyRead()), this, SLOT(recieveCommand()));
		cout << "a" << endl;
		clientSocket->write("hello new client");
		cout << "b" << endl;
	}
	else
		cout << "no pending connections";
}

void italk::recieveCommand()
{
	cout << "new client wants to connect and sended NEW" << endl;
	QString message(clientSocket->readAll());
	cout << "c" << endl;
	cout << message.toStdString() << endl;
	clientSocket->write("OK");
}

italk.h

Code: Alles auswählen

#ifndef italk_H
#define italk_H

#include "ui_italk.h"
#include "logfile.h"
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <QtGui>
#include <QString>
#include <QTranslator>
#include <QTimer>
#include <QKeyEvent>
#include <QtNetwork>
#include <QDataStream>
#include <QByteArray>
#include <QHostAddress>
#include <QAbstractSocket>
#include <QTcpSocket>
#include <QTcpServer>

using namespace std;

class italk : public QMainWindow, public Ui::MainWindow
{
	Q_OBJECT
	public:
		italk(QMainWindow *parent = 0);
		~italk();
		QTcpServer *commandServer;
		QTcpSocket *clientSocket;
	private slots:
		void setServerOnline();
		void newClient();
		void recieveCommand();
};

#endif
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Zwei Dinge
1. readyRead() wird irgendwann aufgerufen - es müssen noch nicht alle Daten vorliegen. Also nicht wundern wenn Du vom Client nicht alles bekommst. Besser (wenn es Text ist) auf canReadLine() checken ob auch wirklich eine komplette Zeile angekommen ist
2. QTcpSocket/Server() bzw. die darunterliegende QIODevice cacht die Daten und sie werden nur versandt wenn der Puffer voll ist bzw. die QIODevice Lust hat. Wenn man sicher gehen will dass es wirklich gesendet wird -> flush()
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
rurseekatze
Beiträge: 7
Registriert: 15. Dezember 2009 17:03

Beitrag von rurseekatze »

Christian81 hat geschrieben:Zwei Dinge
1. readyRead() wird irgendwann aufgerufen - es müssen noch nicht alle Daten vorliegen. Also nicht wundern wenn Du vom Client nicht alles bekommst. Besser (wenn es Text ist) auf canReadLine() checken ob auch wirklich eine komplette Zeile angekommen ist
Werd ich mal ausprobieren, aber das ist eigentlich nicht das Problem. Das Problem ist, dass ich sowohl nicht senden, als auch nichts empfangen kann, jedenfalls wenn es in der Funktion steht, die von readyRead aufgerufen wird. In der anderen Funktion klappt das Versenden komischerweise, denn der Client erhält korrekt das "hello new client".
Christian81 hat geschrieben: 2. QTcpSocket/Server() bzw. die darunterliegende QIODevice cacht die Daten und sie werden nur versandt wenn der Puffer voll ist bzw. die QIODevice Lust hat. Wenn man sicher gehen will dass es wirklich gesendet wird -> flush()
Hab ich jetzt noch nicht ausprobiert, aber das Problem ist, dass das Programm schon beim readAll() bzw. beim write() abstürzt. Daher wird es gar nicht bis zum flush() kommen.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Ok - C++ Basics würde ich sagen...

Code: Alles auswählen

QTcpSocket *clientSocket = commandServer->nextPendingConnection(); 
Das ist sicher nicht das was Du willst und somit ist deine member-Variable clientSocket nicht initialisiert...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
rurseekatze
Beiträge: 7
Registriert: 15. Dezember 2009 17:03

Beitrag von rurseekatze »

Wie würde es denn richtig lauten?
Habe das so schon in verschiedenen Beispielen im Internet so gesehen.
Bin noch nicht so erfahren mit C++, mache es mehr mit learning by doing und ausprobieren, und bisher habe ich so auch immer erreicht, was ich wollte.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Meinen Post durchlesen und fertig!
Du erzeugst eine neue Variable mit dem gleichen Namen wie deine member-Variable - also ist deine Member-Variable unintialisiert!!
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
rurseekatze
Beiträge: 7
Registriert: 15. Dezember 2009 17:03

Beitrag von rurseekatze »

Welche Variable hat denn einen gleichen Namen wie eine Membervariable? Irgendwie stehe ich gerade auf dem Schlauch.
MiKla
Beiträge: 134
Registriert: 29. Juli 2007 15:29

Beitrag von MiKla »

hier:

Code: Alles auswählen

class italk : public QMainWindow, public Ui::MainWindow
{
   Q_OBJECT
   public:
      italk(QMainWindow *parent = 0);
      ~italk();
      QTcpServer *commandServer;
      QTcpSocket *clientSocket;
   private slots:
      void setServerOnline();
      void newClient();
      void recieveCommand();
}; 
und hier:

Code: Alles auswählen

QTcpSocket *clientSocket = commandServer->nextPendingConnection(); 
Michael
rurseekatze
Beiträge: 7
Registriert: 15. Dezember 2009 17:03

Beitrag von rurseekatze »

Danke! Jetzt hab ich's verstanden. Hab da wohl verschiedene Beispiele vermischt und dann ist soetwas herausgekommen.

Hab jetzt einfach

Code: Alles auswählen

QTcpSocket *clientSocket = commandServer->nextPendingConnection(); 
in
clientSocket = commandServer->nextPendingConnection();
geändert und es funktioniert perfekt.
Antworten