[Solved] QTcpServer and Telnet full duplex problem.
-
Hello, thanks for time dedicated to my problem.
I am having a problem developing a threaded server thats gets commands from a telnet console and writes data on it.
Normal operation im looking forward is:
1- Server listens for new connections (telnet client).
2- As new connection appears, a thread is generated.
3- Telnet client sends commands to server to configure message treating.
4- Server can respond with data to telnet client that is shown in console.
5- Items 3 and 4 can be repeated over operation.As i run server, it listens on a port, telnet connects properly, and i can read and process data from console.
As soon as server writes on console, no more commands from telnet console are read on server side (seems like server blocks reading).I am posting some "trimmed" code with more important parts containing communication.
This class waits for new connections and creates threads to work with them
servertotelnet.h
@#include <QTcpServer>
#include <QTcpSocket>
#include <QAbstractSocket>
#include <QFile>
#include "telnetthread.h"class ServerToTelnet : public QTcpServer
{
Q_OBJECTpublic:
explicit ServerToTelnet(QObject *parent = 0);void fireSignal(QByteArray msg); QByteArray bytesOut;
signals:
void msgToTreatSignal(QByteArray);protected:
void incomingConnection(int socketDescriptor);
};@servertotelnet.cpp
@#include "servertotelnet.h"ServerToTelnet ::ServerToTelnet (QObject *parent) :
QTcpServer(parent)
{
listen(QHostAddress::Any, 6000);
}void ServerToTelnet ::incomingConnection(int socketDescriptor)
{
TelnetThread *thread = new TelnetThread(socketDescriptor, this);connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); connect(this, SIGNAL(msgToTreatSignal(QByteArray)), thread, SLOT(msgToTreatSlot(QByteArray))); thread->start();
}
void ServerToTelnet ::fireSignal(QByteArray msg)
{
emit msgToTreatSignal(msg);
}
@This class generates thread code.
telnetthread.h
@#include <QThread>
#include <QTcpSocket>class TelnetThread : public QThread
{
Q_OBJECT
public:
explicit TelnetThread(int ID, QObject *parent = 0);msgType msgToTreat; void run(); void treatMessage(); QString passed(); friend QDataStream &operator>>(QDataStream &bytesIn, msgType &msg);
public slots:
void readCommand();
void disconnected();void msgToTreatSlot(QByteArray); void ListSlot(); void informErrorSlot();
private:
QTcpSocket *client;int socketDescriptor;
};@
telnetthread.cpp
@#include "telnetthread.h"TelnetThread::TelnetThread(int ID, QObject *parent) :
QThread(parent)
{
socketDescriptor = ID;
}void TelnetThread::run()
{
client = new QTcpSocket();client->setSocketDescriptor(socketDescriptor); connect(client, SIGNAL(readyRead()), this, SLOT(readCommand()), Qt::DirectConnection); connect(client, SIGNAL(disconnected()), this, SLOT(disconnected())); exec();
}
void TelnetThread::disconnected()
{
client->deleteLater();
}void TelnetThread::readCommand()
{
QString command;
QFile conditions;command = client->readLine(); conditions.setFileName("conditions.ini"); conditions.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text); conditions.write(command.toAscii()); conditions.close();
}
void TelnetThread::treatMessage()
{
/* Work data */QString result = passed(); client->write(result.toAscii()); client->flush();
}
void TelnetThread::msgToTreatSlot(QByteArray bytesIn)
{
QDataStream streamIn(bytesIn);
streamIn.setVersion(QDataStream::Qt_4_7);streamIn >> msgToTreat; treatMessage();
}
QString TelnetThread::passed()
{
/* QString generation */
return QStringGenerated;
}
@I appreciate your help, i couldn´t find any related topics on Qt documentation/forums.
Thank you very much. -
Hiii mezeq,
Try to make your own Client in Qt as you made Server.
Qt Docs give you such examples which are developed in Qt Whether it is your server or Client. -
Thanks IamSumit,
But a requeriment is to connect through telnet.
That´s why i am asking this, i already tested it with a client of my own and it works properly.
I think there must be a restriction on working with telnet i am not taking in consideration. -
Hmmm mezeq
I think telent has its own behaviour so you cannot identify the state of telnet client. -
Thanks IamSumit
Telnet is based on Protocol TCP/IP, and is supposed to be full-duplex.
I am not so familiar with Telnet, that's why im overlooking some "control" needed to make it work full-duplex.Telnet sends data to my server correctly until server sends data to Telnet. That's the moment when communication turns Half-duplex (from server to telnet).
Telnet console says "Sent string ....." after send command, but i think it may be enqueueing data because in serverside no ready read signal is emmited.
-
I think i'm approaching a solution to Telnet Full-duplex problem.
Although many documentation says that all Telnet consoles work in a Full-duplex mode, I read RFC854 and find out its not true. Default work mode is Half-duplex.
Telnet works with GA (Go Ahead) command when one side of the socket finishes writing data.
There is a command that sets full-duplex mode, the SUPPRESS-GO-AHEAD.
As soon as thread is created (responding to a newConnection on Server) commands "IAC + WILL + SUPPRESS-GO-AHEAD" are sent setting a full-duplex terminal without any command at the end of socket writing.
-
Sending 0xFF, 0xFB, 0x03 to telnet terminal, full-duplex socket connection is guaranteed without need of any other command.
Hope it helps.