Qt 프로세스 간 양방향 통신(QLocalSocket 및 QLocalServer) 구현

7593 단어 Qt
Qt 환경: Qt4
선상 부호
Client:  mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private slots:
    void on_pushButtoLinkServer_clicked();

    void OnReadyRead();

    void on_pushButtonSendMsg_clicked();

private:
    Ui::MainWindow *ui;
    QLocalSocket * m_pSocketReceive;
    QString m_serverName;
};

#endif // MAINWINDOW_H

mainwindow.cpp :
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    m_pSocketReceive(NULL),
    m_serverName("ServerName")
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButtoLinkServer_clicked()
{
    if(NULL == m_pSocketReceive)
    {
        m_pSocketReceive = new QLocalSocket(this);
        m_pSocketReceive->connectToServer(m_serverName);

//        connect(m_pSocketReceive,SIGNAL(connected()),this,SLOT(OnClientConnectSuccess()));
        connect(m_pSocketReceive,SIGNAL(readyRead()),this,SLOT(OnReadyRead()));
    }
}

void MainWindow::OnReadyRead()
{
    if(m_pSocketReceive)
    {
        QDataStream tempReadDataStream(m_pSocketReceive);
        tempReadDataStream.setVersion(QDataStream::Qt_4_8);
        QString str;
        tempReadDataStream >> str;
        ui->lineEditReceiveMsg->setText(str);
    }
}

void MainWindow::on_pushButtonSendMsg_clicked()
{
    if(m_pSocketReceive)
    {
        QDataStream tempWriteDataStream(m_pSocketReceive);
       tempWriteDataStream.setVersion(QDataStream::Qt_4_8);
        QString str = ui->lineEditSendMsg->text();
        tempWriteDataStream << str;
        m_pSocketReceive->waitForBytesWritten();
    }

}

서버:
mainwindow.h 
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 
#include 
#include 

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private slots:
    void on_pushButtonBuildServer_clicked();


    void on_pushButtonSendMsg_clicked();

    void on_pushButtonNewProcess_clicked();

    void OnReceiveNewMsg();

private:
    Ui::MainWindow *ui;

     QLocalServer * m_pLocalServer;
     QLocalSocket * m_pSocketSend;
     QString m_serverName;
     QProcess * m_pProcess;
     QString m_appPath;

};

#endif // MAINWINDOW_H

mainwindow.cpp 
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    m_pLocalServer(NULL),
    m_pSocketSend(NULL),
    m_serverName("ServerName"),
    m_pProcess(NULL),
    m_appPath("/opt/qtcreator-2.6.1/PICDemo/QLocSocketClient-build-desktop-Debug/QLocSocketClient")
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButtonBuildServer_clicked()
{
    if(m_pLocalServer == NULL)
    {
        m_pLocalServer = new QLocalServer(this);
        //        ,  Listen Fail
        QLocalServer::removeServer(m_serverName);
        if(m_pLocalServer->listen(m_serverName))
        {
            ui->lineEditServertate->setText("TRUE");
        }
    }

}

void MainWindow::on_pushButtonSendMsg_clicked()
{
    if(NULL == m_pSocketSend)
    {
        m_pSocketSend = new QLocalSocket(this);
        m_pSocketSend = m_pLocalServer->nextPendingConnection();
        connect(m_pSocketSend,SIGNAL(readyRead()),this,SLOT(OnReceiveNewMsg()));
    }
    if(m_pSocketSend)
    {
        QDataStream tempWriteDataStream(m_pSocketSend);
        tempWriteDataStream.setVersion(QDataStream::Qt_4_8);
        QString str = ui->lineEditSendMsg->text();
        tempWriteDataStream << str;
        m_pSocketSend->waitForBytesWritten();
    }
}

void MainWindow::on_pushButtonNewProcess_clicked()
{
    if(m_pProcess == NULL)
    {
        m_pProcess = new QProcess(this);
        m_pProcess->setEnvironment(m_pProcess->environment());
        m_pProcess->start(m_appPath);
        m_pProcess->waitForStarted();
    }
}

void MainWindow::OnReceiveNewMsg()
{
    QDataStream tempReadDataStream(m_pSocketSend);
    tempReadDataStream.setVersion(QDataStream::Qt_4_8);
    QString str;
    tempReadDataStream >> str;
   ui->lineEditReceiveMsg->setText(str);
}

클라이언트와 서비스 측을 구축함으로써 QLocal Server와 QLocal Socket을 이용하여 통신을 실현할 수 있다.
원리는 제가 가장 권위 있는 공식 F1 매뉴얼을 모시겠습니다.
QLocalServer:
Detailed Description

The QLocalServer class provides a local socket based server.

This class makes it possible to accept incoming local socket connections.

Call listen() to have the server start listening for incoming connections on a specified key. The newConnection() signal is then emitted each time a client connects to the server.

Call nextPendingConnection() to accept the pending connection as a connected QLocalSocket. The function returns a pointer to a QLocalSocket that can be used for communicating with the client.

If an error occurs, serverError() returns the type of error, and errorString() can be called to get a human readable description of what happened.

When listening for connections, the name which the server is listening on is available through serverName().

Calling close() makes QLocalServer stop listening for incoming connections.

Although QLocalServer is designed for use with an event loop, it's possible to use it without one. In that case, you must use waitForNewConnection(), which blocks until either a connection is available or a timeout expires.

QLocalSocket:
Detailed Description

The QLocalSocket class provides a local socket.

On Windows this is a named pipe and on Unix this is a local domain socket.

If an error occurs, socketError() returns the type of error, and errorString() can be called to get a human readable description of what happened.

Although QLocalSocket is designed for use with an event loop, it's possible to use it without one. In that case, you must use waitForConnected(), waitForReadyRead(), waitForBytesWritten(), and waitForDisconnected() which blocks until the operation is complete or the timeout expires.

Note that this feature is not supported on versions of Windows earlier than Windows XP.

 
부딪힌 구덩이를 정리해 보자.
 
1. Linux 환경에서 서버 측 listen은 한 번에 성공할 수 있지만 다시 시작하는 데 실패했습니다. 그러나 listen의 매개 변수, 즉 서버 이름을 바꾸면 성공했습니다.
해결 방법:
//        ,  Listen Fail
        QLocalServer::removeServer(m_serverName);

On Unix if the server crashes without closing listen will fail with AddressInUseError. To create a new server the file should be removed. On Windows two local servers can listen to the same pipe at the same time, but any connections will go to one of the server.
출처:https://stackoverflow.com/questions/15635215/not-able-to-start-qlocalserver 
포럼은 정말 Stackoverflow가 좋아요...국내 포럼을 깎아내릴 뜻은 없다.
 
질문이 있습니다.
QLocalSocket의 connected() 신호가 아예 도착하지 않지만 연결은 성공적이어서 Qt의 BUG인지 모르겠다.
 
교류를 환영합니다.
 
 
 

좋은 웹페이지 즐겨찾기