コードの問題は、whileループでイベントループをブロックしているためです。したがって、問題の解決策は、stdinから非同期で読み取ることです。Linux(およびMacでは、おそらくQSocketNotifier
)では、さまざまなインターネットソースに従って、データがstdinに到着したときに通知し、手動で読み取るために使用できます。
私はWindowsを使用しているので、次のようにすることをお勧めします(すべてのプラットフォームで機能するはずです)。
- stdinからデータを読み取るためのスレッドを開きます
- データ(おそらく行?)を取得したら、Qtシグナルスロットメカニズムを使用して、イベントループをブロックせずにデータをメインスレッドに渡して処理できます。
つまり、これは擬似コードです。MainAppClassは、既存のサーバークラスである必要があります。コンストラクターを編集して新しいスレッドを作成し、データを処理するための新しいスロットを追加します。
class Reader: public QThread
{
Q_OBJECT
public:
Reader(QObject * parent = 0 ): QThread(parent){}
void run(void)
{
forever{
std::string data;
std::getline (std::cin, data);
if(data == "exit")
{
emit exitServer();
return;
}
emit dataReady(QString::fromStdString(data));
}
}
signals:
void dataReady(QString data);
void exitServer();
};
class MainAppClass: public QObject
{
Q_OBJECT
public:
MainAppClass()
{
Reader * tr = new Reader(this);
connect(tr, SIGNAL(dataReady(QString)), this, SLOT(processData(QString)));
connect(tr, SIGNAL(exitServer()), this, SLOT(exitServer()));
tr->start();
}
public slots:
void processData(QString data)
{
std::cout << "Command: " << data.toStdString() << std::endl;
}
void exitServer()
{
std::cout << "Exiting..." << std::endl;
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainAppClass myapp; //your server
app.exec();
return 0;
}
QTcpSocketの使い方の簡単なガイドラインを書いたので、ここに簡単な説明があります
クライアントを取得したら、信号をスロットにQTcpSocket
接続し、オブジェクトからデータを読み取ります。コンストラクターで何も読み取る必要はありません。readyRead()
sender()
読むためにあなたは標準的なQIODevice
機能を使うことができます。
注:これは擬似コードであり、いくつかの変更が必要になる場合があります(読み取り時のストリームの状態の確認、リスト内のソケットへのポインターの保存、シグナルのサブスクライブ、コンストラクターのdisconnected()
呼び出し、リッスンしているかどうかの確認など)。listen()
QTcpServer
onReadyRead()
したがって、クラスに次のコードを持つスロットが必要です。
void Server::readyReadSlot()
{
QTcpSocket *client = (QTcpSocket*)sender(); // get socket which emited the signal
while(client->canReadLine()) // read all lines!
// If there is not any lines received (you may not always receive
// whole line as TCP is stream based protocol),
// you will not leave data in the buffer for later processing.
{
QString line = client->readLine();
processLine(line); // or emit new signal if you like
}
}
内部では、信号をスロットnewConnection()
に接続する必要があります。readyRead()
void Server::newConnection()
{
QTcpSocket *clientSocket = server->nextPendingConnection();
connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
}