QLocalServer和QLocalSocket單進程和進程通信

描述:
QLocalServer 繼承自QObject。QLocalServer提供了一個基於本地套接字(socket)的服務端(server)。它可以接受來自本地socket的連接。server通過調用listen(),監聽特定的連接。newConnection()是在每次server與client連接上時所發出的信號。nextPending- Connection()將等待中的連接當作一個已連接上的QLocalSocket。返回值是指向QLocalSocket的指針,這個QLocalSocket可以與client建立通信。當發生錯誤時,serverError() 返回錯誤的類型,調用errorString()可以獲取對錯誤的描述。 在監聽過程中,通過 server- Name()可以獲取當前server監聽的名稱。close()使QLocalServer停止對連接請求的監聽。雖然QLocalServer是爲在事件循環中使用而設計出來的,但是在沒有事件循環時也是可以使用的。
注意:沒有事件循環時,你必須使用waitForNewConnection(),它只在以下兩種情況下解除阻塞:1)有可用的連接;2)超時。

在Qt中,提供了多種IPC方法,QLocalServer和QLocalSocket算是其一。它的表現看起來好像和Socket搭上點邊,實際它的底層是windows的name pipe(有名管道(QLocalSocket))。它是支持全雙工通信的。QLocalServer主要用來監聽某個管道。建立一個監聽可以這樣做:
(如下)

建立實例:
1. 建立一個QLocalServer實例 m_server
2. 進行listen :

m_server->listen("servername")

3.當有連接到來時,QLocalServer會發送netConnection()信號,所以進行信號連接, 在init()函數中:

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

4.在newConnection()函數中取得連接客戶端的QLocalSocket

QLocalSocket *newsocket = m_server->nextPendingConnection();

5.當QLocalSocket可以讀數據時它會發送readyRead()信號,所以對newsocket進行信號連接, 在newConnection()函數中:

   connect(newsocket, SIGNAL(readyRead()), this, SLOT(readyRead()));

6.在readyRead()函數中讀取數據:
// 取得是哪個localsocket可以讀數據了

     QLocalSocket *local = static_cast<QLocalSocket *>(sender()); 
        if (!local) return;
        QTextStream in(local);
        QString     readMsg;
        // 讀出數據
        readMsg = in.readAll();

全部代碼, server端:
// server.h

#ifndef SERVER_H
#define SERVER_H
#include <QLocalServer>
#include <QLocalSocket>
class Server : public QObject
{
    Q_OBJECT
public:
    Server()
    {
        m_server = 0;
    } 
    ~Server()
    {
        if (m_server) {
            delete m_server;
        }
    }
    int init(const QString & servername)
    {
        // 如果已經有一個實例在運行了就返回0
        if (isServerRun(servername)) {
            return 0;
        }
        m_server = new QLocalServer;
        // 先移除原來存在的,如果不移除那麼如果
        // servername已經存在就會listen失敗
        QLocalServer::removeServer(servername);
        // 進行監聽
        m_server->listen(servername);
        connect(m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
        return 1;
    }
private slots:
    // 有新的連接來了
    void newConnection()
    {
        QLocalSocket *newsocket = m_server->nextPendingConnection(); 
        connect(newsocket, SIGNAL(readyRead()), this, SLOT(readyRead()));
    }  
    // 可以讀數據了
    void readyRead()
    {
        // 取得是哪個localsocket可以讀數據了
        QLocalSocket *local = static_cast<QLocalSocket *>(sender()); 
        if (!local) return;
        QTextStream in(local);
        QString     readMsg;
        readMsg = in.readAll(); // 讀出數據
        emit newMessage(readMsg);// 發送收到數據信號
    }
private:
    // 判斷是否有一個同名的服務器在運行
    int isServerRun(const QString & servername)
    {
        // 用一個localsocket去連一下,如果能連上就說明
        // 有一個在運行了
        QLocalSocket ls;
        ls.connectToServer(servername);
        if (ls.waitForConnected(1000)){ 
            ls.disconnectFromServer();// 說明已經在運行了
            ls.close();
            return 1;
        }
        return 0;
    }
signals:
    void newMessage(const QString &msg);
private:
    QLocalServer *m_server;
};
#endif // SERVER_H

///////////////////////////////////////////////////////////////////////
/// main.cpp
///////////////////////////////////////////////////////////////////////

#include <QApplication>
#include <QLabel>
#include <QMessageBox>
#include "server.h"
int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QLabel       text("teststts");
    Server       s;
    if (!s.init("localserver-test")){
        // 初使化失敗, 說明已經有一個在運行了
        QMessageBox::information(&text, "info", "There is already exist one!"); 
        return 1;
    }
    QObject::connect(&s, SIGNAL(newMessage(const QString &)),&text, SLOT(setText(const QString &)));
    text.show();
    return app.exec();
}

用於測試的客戶端代碼, 每一秒向server發送一個隨機數: 
 #include <QLoacalSocket>
 #include <stdlib.h>
 #include <unistd.h>
int main(int argc, char **argv)
{
    QLocalSocket ls;
    ls.connectToServer("localserver-test");
    srandom(1000);

    if (ls.waitForConnected()){
        while (1){
            QTextStream ts(&ls);
            ts << QString::number(random()) + "\nTTTTTTTTTT" + "\nXXXXXXXX";
            ts.flush();
            ls.waitForBytesWritten();
            sleep(1);
        }
    }
    return 0;
}

先運行server程序, 然後運行測試用的客戶端…

本來參照 http://www.aiuxian.com/article/p-3105197.html
http://blog.chinaunix.net/uid-20718335-id-1993073.html 加以修改和實現

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章