2013-02-04 59 views
2

我正在編寫一個服務器作爲Qt控制檯應用程序。我有服務器設置爲等待套接字連接,但我還需要允許用戶輸入命令到服務器進行管理。兩者都獨立工作。然而,我遇到的問題是,當我在一個while循環接受和處理輸入命令時,服務器不接受連接。Qt C++控制檯服務器,等待套接字連接並同時接受輸入?

我有一個Socket類,並在它的構造,我有:

connect(server,SIGNAL(newConnection()),this, SLOT(newConnection())); 

權下,在構造函數中,我認爲那是有一個更深入的版本,本作從得到命令的功能用戶:

QTextStream qin(stdin, QIODevice::ReadOnly); 
QString usrCmd; 

while(usrCmd != "exit" && usrCmd != "EXIT") { 
    //Get command input and process here 
} 

在newConnection()中,我只接受下一個連接,然後使用套接字。

QTcpSocket *serverSocket = server->nextPendingConnection(); 

我怎樣才能使這樣的插座可以等待連接等待用戶inputed命令在同一時間?

回答

2

您的代碼存在問題,因爲您使用while循環阻止事件循環。所以,你的問題的解決方案是從stdin異步讀取。在Linux上(在Mac上,我猜),您可以使用QSocketNotifier來通知數據何時到達stdin,並手動讀取),如各種互聯網源。

由於我使用的是Windows,我建議你做這樣(應在所有平臺上工作):

  1. 打開線程從標準
  2. 一旦你得到一些讀取數據數據(可能是行?),您可以使用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,這裏是短暫

當你的客戶QTcpSocketreadyRead()信號連接到某些插槽,並從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 
    } 
} 

裏面你需要readyRead()信號與插槽連接newConnection()

void Server::newConnection() 
{ 
    QTcpSocket *clientSocket = server->nextPendingConnection(); 
    connect(clientSocket, SIGNAL(readyRead()), this, SLOT(readyReadSlot())); 
} 
+0

我很困惑你的答案。根據我對你所說的話的理解,這不是解決我的問題的方法。但我可能會誤解你。 – Mitch

+0

不,我誤解了你 - 我正在閱讀我的手機!對不起,我現在編輯我的答案。 –

+0

@Mitch,請參閱我編輯的第一部分。 –

相關問題