2013-09-22 36 views
14

Windows上で名前付きパイプを使用する場合は、QLocalSocketを使用できます。 Qtでサーバーとクライアントプログラムを作成しています。パイプラインでメッセージを書き込むためにWIN32 APIを使用しようとすると、Qtクライアントはそれを表示しません。また、クライアントがWIN32 APIを使用して再度書き込む場合、Qtサーバは送信されたメッセージをエコーし​​ません。 QLocalSocketは本当に名前付きパイプに対して推奨されていますか?実際に名前付きパイプにQLocalSocketが使用されていますか

これはこれは、Win32クライアント側での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; 

です:

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

すべてのコードを実行することなく、私はこれを肯定的に回答できます。ここでは別のQtアプリの名前付きパイプにQtのアプリからの書き込み作業のアプリからいくつかのコードは、(それが最小化され、別のアプリを復元する)です:

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

アプリは、このようにセット物事を復元する:

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サーバから読み込みます。それがうまくいかないのであれば、フレームワークの互換性に問題があります。このような状況で確かめるべきことの1つは、プロセスがブロックされないようにすることです。その理由は次のとおりです。私はそれを読む前に読み込みが完了していることを確認します。私はQtを使っていませんでしたが、M $側で書いた後でパイプをフラッシュしなければならないかもしれません。

(印刷、印刷プレビュー、ページ設定、またはファイルダイアログのブラウズが開いていると、Qtメッセージループが停止し、このようなメッセージに対してアプリケーションが応答しなくなることがわかりました。フォントダイアログ(OTOH)は、親アプリケーションをブロックしません。

関連する問題