2013-09-22 11 views
14

Gemäß der Qt-Dokumentation, wenn wir Named Pipes in Windows verwenden möchten, können wir QLocalSocket verwenden. Ich schreibe ein Server und Client-Programm mit Qt. Wenn ich versuche, die WIN32-API zu verwenden, um eine Nachricht in die Pipe-Zeile zu schreiben, zeigt der Qt-Client sie nicht an. Wenn der Client erneut mithilfe der WIN32-API schreibt, gibt der Qt-Server die gesendete Nachricht nicht zurück. Wird QLocalSocket wirklich für Named Pipes empfohlen?Wird QLocalSocket wirklich für Namedpipes verwendet?

Dies ist der Server-Code Win32

 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; 

Dies ist die Win32-Client-Seite:

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; 

Dies ist die Qt Server-Seite

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"); 
} 

Dies ist die Qt Client-Seite

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

Welche Version von Windows verwenden Sie für die Tests? – mhcuervo

+0

Windows 8, 64 bit – paytam

+0

Geben Sie einen vollständigen Pfad zur Named-Pipe-Datei an oder verwenden Sie einfach den Dateinamen? Wenn es nur der Dateiname ist, kann es sein, dass die Pipe nicht gefunden wird. – TheDarkKnight

Antwort

1

Ohne Ihren gesamten Code durchzugehen, kann ich dies bejahen. Hier ist ein Code aus einer Arbeits-Anwendung, die von einem Qt-App auf eine Named Pipe in einem anderen Qt App schreibt (es wieder eine andere Anwendung, die minimiert wird):

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(); 

Die App setzen Dinge gestellt wird bis so:

localServer = new QLocalServer(this); 

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

Wenn es Zeit wird, die Nachricht zu lesen, ich mache es wie folgt aus:

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); 

es kann gut sein, dass Qt Named Pipes und M Rohre $ genannt sind irgendwie nicht kompatibel. Ich schlage vor, eine M $ -Framework-App zu schreiben, um in den M $ -Framework-Client zu schreiben, und eine M $ -Framework-Anwendung zu lesen, um sicherzustellen, dass sie beide richtig funktionieren. Ersetzen Sie dann eine Qt-App, um vom Qt-Server zu lesen. Wenn das nicht funktioniert, handelt es sich um eine Art von Framework-Inkompatibilität (obwohl ich davon ausgehe, dass beide mit dem Betriebssystem ordnungsgemäß interagieren). In Situationen wie diesen muss man sicherstellen, dass die Prozesse nicht blockiert werden. Deshalb z. Ich stelle sicher, dass das Lesen fertig ist, bevor ich es lese. Möglicherweise müssen Sie auch die Pipe nach dem Schreiben auf der Seite M $ spülen, obwohl ich nicht mit Qt.

(Ich habe festgestellt, dass, wenn ein Drucken, Seitenansicht, Seite einrichten oder nach Datei suchen Dialogfeld geöffnet ist, stoppt die Qt-Nachrichtenschleife, und die App wird auf solche Nachrichten nicht reagieren Schriftdialog, OTOH, blockiert nicht die übergeordnete App. Go Abbildung.)

Verwandte Themen