2013-09-22 2 views
14

Windows에서 명명 된 파이프를 사용하려면 QLocalSocket을 사용할 수 있습니다. Qt로 서버 및 클라이언트 프로그램을 작성 중입니다. 파이프 라인에서 일부 메시지를 쓰려고 WIN32 API를 사용하려고하면 Qt 클라이언트가 메시지를 표시하지 않습니다. 또한 클라이언트가 WIN32 API를 사용하여 다시 쓰는 경우 Qt 서버는 보낸 메시지를 표시하지 않습니다. 명명 된 파이프에 QLocalSocket이 정말로 권장됩니까?실제로 QLocalSocket이 명명 된 파이프에 실제로 사용됩니까

이는 Win32 Server 코드

 wcout << "Creating an instance of a named pipe..." << endl; 
    // Create a pipe to send data 
    HANDLE pipe = CreateNamedPipeW(
     L"\\\\.\\pipe\\ServicePipe", // name of the pipe 
     PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only 
     PIPE_TYPE_BYTE, // send data as a byte stream 
     100, // only allow 1 instance of this pipe 
     0, // no outbound buffer 
     0, // no inbound buffer 
     0, // use default wait time 
     NULL // use default security attributes 
     ); 

    if (pipe == NULL || pipe == INVALID_HANDLE_VALUE) { 
     wcout << "Failed to create outbound pipe instance."; 
     // look up error code here using GetLastError() 
     system("pause"); 
     return 1; 
    } 

    wcout << "Waiting for a client to connect to the pipe..." << endl; 

    // This call blocks until a client process connects to the pipe 
    BOOL result = ConnectNamedPipe(pipe, NULL); 
    if (!result) { 
     wcout << "Failed to make connection on named pipe." << endl; 
     // look up error code here using GetLastError() 
     CloseHandle(pipe); // close the pipe 
     system("pause"); 
     return 1; 
    } 

    wcout << "Sending data to pipe..." << endl; 

    // This call blocks until a client process reads all the data 
    wcout <<endl<<"Input your message: "; 

    wstring data=L""; 
    getline(wcin,data); 
    DWORD numBytesWritten = 0; 
    result = WriteFile(
     pipe, // handle to our outbound pipe 
     data.c_str(), // data to send 
     wcslen(data.c_str()) * sizeof(wchar_t), // length of data to send (bytes) 
     &numBytesWritten, // will store actual amount of data sent 
     NULL // not using overlapped IO 
     ); 


    if (result) { 
     wcout << "Number of bytes sent: " << numBytesWritten << endl; 
    } else { 
     wcout << "Failed to send data." << endl; 
     // look up error code here using GetLastError() 
    } 

    // Close the pipe (automatically disconnects client too) 
    CloseHandle(pipe); 

    wcout << "Done." << endl; 

이는 Win32 클라이언트 측입니다 :

wcout << "Connecting to pipe..." << endl; 
    // Open the named pipe 
    // Most of these parameters aren't very relevant for pipes. 
    HANDLE pipe = CreateFileW(
     L"\\\\.\\pipe\\ServicePipe", 
     GENERIC_READ, // only need read access 
     FILE_SHARE_READ | FILE_SHARE_WRITE, 
     NULL, 
     OPEN_EXISTING, 
     FILE_ATTRIBUTE_NORMAL, 
     NULL 
     ); 

    if (pipe == INVALID_HANDLE_VALUE) { 
     wcout << "Failed to connect to pipe." << endl; 
     // look up error code here using GetLastError() 
     system("pause"); 
     return 1; 
    } 

    wcout << "Reading data from pipe..." << endl; 

    // The read operation will block until there is data to read 
    wchar_t buffer[128]; 
    DWORD numBytesRead = 0; 
    BOOL result = ReadFile(
     pipe, 
     buffer, // the data from the pipe will be put here 
     127 * sizeof(wchar_t), // number of bytes allocated 
     &numBytesRead, // this will store number of bytes actually read 
     NULL // not using overlapped IO 
     ); 

    if (result) { 
     buffer[numBytesRead/sizeof(wchar_t)] = '?'; // null terminate the string 
     wcout << "Number of bytes read: " << numBytesRead << endl; 
     wcout << "Message: " << buffer << endl; 
    } else { 
     wcout << "Failed to read data from the pipe." << endl; 
    } 

    // Close our pipe handle 
    CloseHandle(pipe); 

    wcout << "Done." << endl; 

이것은 Qt는 서버 측이

LocalSocketIpcServer::LocalSocketIpcServer(QString servername, QObject *parent) 
:QObject(parent) { 
m_server = new QLocalServer(this); 
if (!m_server->listen(servername)) { 
    showMessage("Not able to start the Server"); 
} 

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

LocalSocketIpcServer::~LocalSocketIpcServer() { 

} 


void LocalSocketIpcServer::socket_new_connection() { 

QLocalSocket *clientConnection = m_server->nextPendingConnection(); 

while (clientConnection->bytesAvailable() < (int)sizeof(quint32)) 
    clientConnection->waitForReadyRead(); 



//connect(clientConnection,SIGNAL(readyRead()),clientConnection,SLOT(rea)); 
connect(clientConnection, SIGNAL(disconnected()),clientConnection, SLOT(deleteLater())); 

QDataStream in(clientConnection); 
in.setVersion(QDataStream::Qt_5_1); 
if (clientConnection->bytesAvailable() < (int)sizeof(quint16)) { 
    return; 
} 

QString message; 
in >> message; 

QByteArray block; 
QDataStream out(&block, QIODevice::WriteOnly); 
QString msg=+"Message recieved with content "+message+"\n"; 
out.setVersion(QDataStream::Qt_5_1); 
out <<msg; 
out.device()->seek(0); 
clientConnection->write(block); 
clientConnection->flush(); 
clientConnection->disconnectFromServer(); 

emit messageReceived(message); 
} 


void LocalSocketIpcServer::showMessage(QString msg) 
{ 
QMessageBox m; 
m.setText(msg); 
m.exec(); 
} 
LocalSocketIpcServer::FrmMain(QWidget *parent) :QMainWindow(parent),ui(new Ui::FrmMain) 
{ 
ui->setupUi(this); 

m_server = new LocalSocketIpcServer("\\\\.\\pipe\ServicePipe", this); 
connect(m_server, SIGNAL(messageReceived(QString)), this, SLOT(messageReceived(QString))); 
} 

LocalSocketIpcServer::~FrmMain() 
{ 
delete ui; 
} 

void LocalSocketIpcServer::messageReceived(QString message) 
{ 
    ui->textBrowser->append(message+"\n"); 
} 

이것은 Qt는 클라이언트 쪽

LocalSocketIpcClient::LocalSocketIpcClient(QString remoteServername, QObject *parent) : 
    QObject(parent) { 

m_socket = new QLocalSocket(this); 
m_serverName = remoteServername; 

connect(m_socket, SIGNAL(connected()), this, SLOT(socket_connected())); 
connect(m_socket, SIGNAL(disconnected()), this, SLOT(socket_disconnected())); 

connect(m_socket, SIGNAL(readyRead()), this, SLOT(socket_readReady())); 
connect(m_socket, SIGNAL(error(QLocalSocket::LocalSocketError)), 
     this, SLOT(socket_error(QLocalSocket::LocalSocketError))); 
} 

LocalSocketIpcClient::~LocalSocketIpcClient() { 
m_socket->abort(); 
delete m_socket; 
m_socket = NULL; 
} 

QString LocalSocketIpcClient::Read() 
{ 

QDataStream in(this->m_socket); 
in.setVersion(QDataStream::Qt_5_1); 

if (m_socket->bytesAvailable() < (int)sizeof(quint16)) { 
    return "No data available"; 
} 

QString message; 
in >> message; 
return message; 
} 

void LocalSocketIpcClient::send_MessageToServer(QString message) { 
m_socket->abort(); 
m_message = message; 
m_socket->connectToServer(m_serverName,QIODevice::ReadWrite); 
} 


void LocalSocketIpcClient::socket_connected(){ 
QByteArray block; 
QDataStream out(&block, QIODevice::ReadWrite); 
out.setVersion(QDataStream::Qt_5_1); 
out << m_message; 
out.device()->seek(0); 
m_socket->write(block); 
m_socket->flush(); 
} 

void LocalSocketIpcClient::socket_disconnected() { 
//showMessage("Client socket_disconnected"); 
} 


void LocalSocketIpcClient::socket_readReady() { 
//showMessage("Client socket read Ready"); 

QDataStream in(this->m_socket); 
in.setVersion(QDataStream::Qt_5_1); 

if (m_socket->bytesAvailable() < (int)sizeof(quint16)) { 
    return; 
} 

QString message; 
in >> message; 
emit RecievedDataFromServer(message); 

} 

void LocalSocketIpcClient::socket_error(QLocalSocket::LocalSocketError e) { 
/* 
QString errorMessage="Client socket_error:"; 

switch (e) { 
case QLocalSocket::ConnectionRefusedError: 
    errorMessage+="The connection was refused by the peer (or timed out)."; 
    break; 

case QLocalSocket::PeerClosedError: 
    errorMessage+="The remote socket closed the connection. Note that the client socket (i.e., this socket) will be closed after the remote close notification has been sent."; 
    break; 

case QLocalSocket::ServerNotFoundError: 
    errorMessage+="The local socket name was not found."; 
    break; 

case QLocalSocket::SocketAccessError: 
    errorMessage+="The socket operation failed because the application lacked the required privileges."; 
    break; 

case QLocalSocket::SocketResourceError: 
    errorMessage+="The local system ran out of resources (e.g., too many sockets)."; 
    break; 

case QLocalSocket::SocketTimeoutError: 
    errorMessage+="The socket operation timed out."; 
    break; 

case QLocalSocket::DatagramTooLargeError: 
    errorMessage+="The datagram was larger than the operating system's limit (which can be as low as 8192 bytes)."; 
    break; 

case QLocalSocket::ConnectionError: 
    errorMessage+="An error occurred with the connection."; 
    break; 

case QLocalSocket::UnsupportedSocketOperationError: 
    errorMessage+="The requested socket operation is not supported by the local operating  system."; 
    break; 

case QLocalSocket::UnknownSocketError: 
    errorMessage+="An unidentified error occurred."; 
    break; 

default: 
    break; 
} 
showMessage(errorMessage); 
*/ 
} 

void LocalSocketIpcClient::showMessage(QString msg) 
{ 
QMessageBox m; 
m.setText(msg); 
m.exec(); 
} 
LocalSocketIpcClient::SingleMessageSend(QWidget *parent) : 
QDialog(parent), 
ui(new Ui::SingleMessageSend) 
{ 
ui->setupUi(this); 

client = new LocalSocketIpcClient("\\\\.\\pipe\ServicePipe", this); 
connect(this->client,SIGNAL(RecievedDataFromServer(QString)),this,SLOT(UpdateGUI(QString))); 
} 

LocalSocketIpcClient::~SingleMessageSend() 
{ 
delete ui; 
} 

void SingleMessageSend::on_pushButton_clicked() 
{ 
QString msg=this->ui->lineEdit->text().trimmed(); 
client->send_MessageToServer(msg); 

} 

void SingleMessageSend::UpdateGUI(QString message) 
{ 
ui->textEdit->insertPlainText(message+"\n"); 
} 

void SingleMessageSend::on_pushButton_2_clicked() 
{ 
ui->textEdit->insertPlainText(client->Read()+QString("\n")); 
} 
+0

테스트에 사용중인 Windows 버전은 무엇입니까? – mhcuervo

+0

Windows 8, 64 비트 – paytam

+0

명명 된 파이프 파일의 전체 경로를 지정 하시겠습니까? 아니면 파일 이름을 사용하고 있습니까? 파일 이름 일 뿐이라면 파이프를 찾지 못할 수도 있습니다. – TheDarkKnight

답변

1

코드를 모두 거치지 않고이를 긍정적으로 대답 할 수 있습니다. 최대 따라서 세트의 일을 복원 할

QLocalSocket ls; 
ls.connectToServer("Restore Server", QIODevice::WriteOnly); 
if (!ls.waitForConnected(5000)) 
{ 
     qDebug(ls.errorString().toUtf8()); 
     return false; 
} 
ls.write("raise"); 
if (!ls.waitForBytesWritten(5000)) 
{ 
     qDebug(ls.errorString().toUtf8()); 
     return false; 
} 
ls.disconnectFromServer(); 

응용 : 여기에 또 다른 Qt는 응용 프로그램에서 명명 된 파이프에 Qt는 응용 프로그램에서 기록 작업 응용 프로그램에서 일부 코드가 (이 최소화 다른 응용 프로그램을 복원)

이 메시지를 읽을 시간이 올 때
localServer = new QLocalServer(this); 

connect(localServer, SIGNAL(newConnection()), this, 
    SLOT(messageFromOtherInstance())); 
localServer->listen("Restore Server"); 

, 나는 이런 식으로 작업을 수행합니다

QLocalSocket *localSocket = localServer->nextPendingConnection(); 
if (!localSocket->waitForReadyRead(5000)) 
{ 
     qDebug(localSocket->errorString().toLatin1()); 
     return; 
} 
QByteArray byteArray = localSocket->readAll(); 
QString message = QString::fromUtf8(byteArray.constData()); 

if (message == "raise") 
    bringToTop(this); 

그것은 잘 Qt는이 명명 된 파이프와 M $ 명명 된 파이프를 든 호환되지 않는 것을 할 수있다. 나는 M $ 프레임 워크 애플리케이션을 작성하여 M $ 프레임 워크 클라이언트와 M $ 프레임 워크 애플리케이션으로 작성하여 양쪽 모두 올바르게 작동하는지 확인하는 것이 좋습니다. 그런 다음 Qt 응용 프로그램을 대체하여 Qt 서버에서 읽습니다. 그것이 작동하지 않는다면, 그것은 일종의 프레임 비 호환성입니다 (비록 그들이 둘 다 OS와 적절하게 상호 작용할 것을 기대하기는하지만). 이와 같은 상황에서 확실한 한 가지는 프로세스가 차단되지 않도록하는 것입니다. 그 이유는 나는 그것을 읽기 전에 읽음이 준비되어 있는지 확인한다. Qt를 사용하지 않았더라도 M $ 쪽에서 작성한 후에 파이프를 플러시해야 할 수도 있습니다.

(인쇄, 인쇄 미리보기, 페이지 설정 또는 파일 찾아보기 대화 상자가 열려 있으면 Qt 메시지 루프가 중단되고 응용 프로그램이 이와 같은 메시지에 응답하지 않는다는 것을 알았습니다. 글꼴 대화 상자, OTOH는 상위 응용 프로그램을 차단하지 않습니다.)