ich habe folgendes Problem: Habe ein kleines Client-Server Programm geschrieben (siehe http://miloi.de/priv/pingpong.zip), bei dem der Client sich mit dem Server verbindet und ein "PING" zum Server schickt. Darauf soll der Server mit "PONG" antworten, worauf wieder ein "PING" vom Client kommen soll usw. Leider klappt das nicht, weil das "PING" nie geschickt wird. Die Socketverbindung wird aufgebaut, aber sock->write() schickt nichts über den Socket, obwohl danach sogar sock->flush() aufgerufen wird. Eine Event Loop ist ebenfalls vorhanden.
Meine Vermutung ist, dass flush() nur bewirkt, dass der QTcpSocket Puffer and den Betriebssystem-TCP-Socket geschrieben wird, aber nicht, dass die Daten tatsächlich auch übertragen werden. Falls das so ist, muss es doch aber irgendeine Möglichkeit geben, das BS dazu zu veranlassen, die Daten rauszuschicken. Jedes Client-Server-System lebt doch von Requests und Replies?! Oder ist der Fehler doch im Code (siehe http://miloi.de/priv/pingpong.zip). Habe tagelang erfolglos versucht, das Problem ausfindig zu machen, wäre also für jeden Tipp, Hinweis oder jede Meinung dankbar! Code siehe unten.
Qt: 4.3.1 Commercial und OSS
BS: Win XP SP2, OpenSuSE Linux 10.2 und FreeBSD 6.2
Gruß
Titus
PingpongClient.h:
Code: Alles auswählen
#include <QTcpSocket>
class PingpongClient : public QTcpSocket
{
Q_OBJECT
public:
PingpongClient();
private slots:
void ping();
void readPong();
void displayError(QAbstractSocket::SocketError socketError);
private:
int blockSize;
};Code: Alles auswählen
#include "PingpongClient.h"
#include <QCoreApplication>
#include <QDataStream>
#include <QByteArray>
#include <string>
#include <iostream>
PingpongClient::PingpongClient() : QTcpSocket()
{
connect(this, SIGNAL(readyRead()), this, SLOT(readPong()));
connect(this, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(displayError(QAbstractSocket::SocketError)));
connect(this, SIGNAL(connected()), this, SLOT(ping()));
}
void PingpongClient::ping()
{
std::cout << "Sending PING!" << std::endl;
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint16)0;
out << "PING!";
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));
blockSize = 0;
write(block);
flush();
}
void PingpongClient::readPong()
{
QDataStream in(this);
in.setVersion(QDataStream::Qt_4_0);
if (blockSize == 0)
{
if (bytesAvailable() < (int)sizeof(quint16))
return;
in >> blockSize;
}
if (bytesAvailable() < blockSize)
return;
QString line;
in >> line;
std::cout << "Response: " << line.toAscii().data() << std::endl;
ping();
}
void PingpongClient::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError) {
case QAbstractSocket::RemoteHostClosedError:
std::cout << "Connection closed by server" << std::endl;
break;
case QAbstractSocket::HostNotFoundError:
std::cout << "Host not found" << std::endl;
break;
case QAbstractSocket::ConnectionRefusedError:
std::cout << "Connection refused" << std::endl;
break;
default:
std::cout << "Error: " << errorString().toAscii().data() << std::endl;
}
exit(0);
}
/******************************************************************************/
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
PingpongClient client;
client.connectToHost("127.0.0.1", 4242);
return app.exec();
}Code: Alles auswählen
#include <QTcpServer>
#include <QTcpSocket>
class PingpongServer : public QTcpServer
{
Q_OBJECT
public:
PingpongServer();
virtual ~PingpongServer();
private slots:
void openConnection();
void pong();
void readPing();
void clientDisconnect();
void displayError(QAbstractSocket::SocketError socketError);
private:
QTcpSocket *sock;
int blockSize;
};Code: Alles auswählen
#include "PingpongServer.h"
#include <QCoreApplication>
#include <QDataStream>
#include <QByteArray>
#include <string>
#include <iostream>
PingpongServer::PingpongServer() : QTcpServer()
{
sock = NULL;
connect(this, SIGNAL(newConnection()), this, SLOT(openConnection()));
}
PingpongServer::~PingpongServer()
{
clientDisconnect();
}
void PingpongServer::openConnection()
{
if (sock != NULL)
std::cout << "Client already connected" << std::endl;
else
{
blockSize = 0;
sock = nextPendingConnection();
connect(sock, SIGNAL(disconnected()), this, SLOT(clientDisconnect()));
connect(sock, SIGNAL(readyRead()), this, SLOT(readPing()));
connect(sock, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(displayError(QAbstractSocket::SocketError)));
}
}
void PingpongServer::pong()
{
if (sock == NULL)
return;
std::cout << "Sending PONG!" << std::endl;
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint16)0;
out << "PONG!";
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));
blockSize = 0;
sock->write(block);
sock->flush();
}
void PingpongServer::readPing()
{
if (sock == NULL)
return;
QDataStream in(sock);
in.setVersion(QDataStream::Qt_4_0);
if (blockSize == 0)
{
if (sock->bytesAvailable() < (int)sizeof(quint16))
return;
in >> blockSize;
}
if (sock->bytesAvailable() < blockSize)
return;
QString line;
in >> line;
std::cout << "Response: " << line.toAscii().data() << std::endl;
pong();
}
void PingpongServer::clientDisconnect()
{
if (sock != NULL)
{
sock->deleteLater();
sock = NULL;
}
}
void PingpongServer::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError) {
case QAbstractSocket::RemoteHostClosedError:
std::cout << "Connection closed by client" << std::endl;
break;
case QAbstractSocket::HostNotFoundError:
std::cout << "Host not found" << std::endl;
break;
case QAbstractSocket::ConnectionRefusedError:
std::cout << "Connection refused" << std::endl;
break;
default:
if (sock != NULL)
std::cout << "Error: " << sock->errorString().toAscii().data() << std::endl;
else
std::cout << "Unknown error" << std::endl;
}
exit(0);
}
/******************************************************************************/
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
PingpongServer server;
if (!server.listen(QHostAddress::Any, 4242))
{
std::cout << "Could not start server" << std::endl;
return 0;
}
return app.exec();
}