2016-06-06 19 views
0

Ich lerne, wie man Dateideskriptoren unter Verwendung von Unix Domain Sockets mit Qt 5.6 unter Ubuntu 14.04 übergibt. Aus der Dokumentation geht hervor, dass dies mit den Klassen QLocalServer und QLocalSocket geschieht.Qt 5.6 Übergeben von Dateideskriptoren mit QLocalServer und QLocalSocket

Ich habe 2 einfache Anwendungen, 1 Server und 1 Client erstellt. Sie haben jeweils nur eine Klasse und ich habe die gesamte Klasse darunter eingefügt.

kann ich die ‚Dateideskriptors‘ als eine ganze Zahl erhalten, aber wenn ich versuche es Modus in append zu öffnen, so kann ich es in dem Client-Prozess schreiben, erhalte ich folgende Fehlermeldung:

Cannot open existing file handle: "Unknown error" 
QIODevice::write: device not open 
FD Received: 20 

Was mache ich falsch?

Auftraggeber:

#include <QtWidgets> 
#include <QtNetwork> 

#include "localclient.h" 

Client::Client(QObject *parent) 
{ 

    socket = new QLocalSocket(this); 
    connect(socket, SIGNAL(readyRead()), this, SLOT(readFd())); 
    connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(displayError(QLocalSocket::LocalSocketError))); 

    requestFd(); 

} 

void Client::requestFd() 
{ 

    socket->abort(); 
    socket->connectToServer("mysocket"); 

} 

void Client::readFd() 
{ 

    QDataStream in(socket); 
    in.setVersion(QDataStream::Qt_4_0); 

    if (socket->bytesAvailable() < (int)sizeof(quint16)) 
     return; 

    if (in.atEnd()) 
     return; 

    int nextFd; 
    in >> nextFd; 

    QFile rxFile; 
    if (!rxFile.open(nextFd,QIODevice::Append)) { 
     qDebug() << "Cannot open existing file handle: " << rxFile.errorString(); 
    } 
    rxFile.write("hello"); 

    qDebug() << "FD Received: " << nextFd; 

} 

void Client::displayError(QLocalSocket::LocalSocketError socketError) 
{ 
    switch (socketError) { 
    case QLocalSocket::ServerNotFoundError: 
     tr("The host was not found. Please check the " 
      "host name and port settings."); 
     break; 
    case QLocalSocket::ConnectionRefusedError: 
     tr("The connection was refused by the peer. " 
      "Make sure the fortune server is running, " 
      "and check that the host name and port " 
      "settings are correct."); 
     break; 
    case QLocalSocket::PeerClosedError: 
     break; 
    default: 
     tr("The following error occurred: %1.").arg(socket->errorString()); 
    } 

} 

Server:

#include <QtWidgets> 
#include <QtNetwork> 

#include <stdlib.h> 

#include "localserver.h" 
#include <qlocalserver.h> 
#include <qlocalsocket.h> 

Server::Server(QObject *parent) 
{ 

    server = new QLocalServer(this); 
    if (!server->listen("mysocket")) { 
     qDebug() << QString("Unable to start the server: %1.").arg(server->errorString()); 
     return; 
    } 

    qDebug() << tr("The server is running"); 

    connect(server, SIGNAL(newConnection()), this, SLOT(sendFd())); 

    fileToSend = new QFile("/home/me/Desktop/test.bin"); 
    if (!fileToSend->open(QIODevice::WriteOnly)) { 
     qDebug() << "Unable to open file to send"; 
    } 

} 

void Server::sendFd() 
{ 

    QByteArray block; 
    QDataStream out(&block, QIODevice::WriteOnly); 
    out.setVersion(QDataStream::Qt_4_0); 
    out.device()->seek(0); 
    qDebug() << "Sending this file handle: " << fileToSend->handle(); 
    out << fileToSend->handle(); 

    QLocalSocket *clientConnection = server->nextPendingConnection(); 
    connect(clientConnection, SIGNAL(disconnected()), 
      clientConnection, SLOT(deleteLater())); 

    clientConnection->write(block); 
    clientConnection->flush(); 
    clientConnection->disconnectFromServer(); 

} 

Antwort

1

Unter Linux Senden Filedeskriptoren Unix-Domain-Sockets unter Verwendung SCM_RIGHTS Zusatzdaten vom Typ getan werden. Qt scheint solche Daten unter Verwendung QLocalSocket und QLocalServer nicht zu unterstützen, gibt es eine alte QTBUG über das Problem zu sprechen. Und es scheint, dass es noch nicht gelöst worden ist.

können Sie die Qt D-Bus verwenden, wo Sie Filedeskriptoren mit QDBusUnixFileDescriptor class.Or senden kann ich fürchte, Sie müssen möglicherweise Unix-Domain-Sockets verwenden zu implementieren, dass Sie sich, es ist ein gutes Beispiel here.

Aber sind Sie sicher, dass Sie wirklich Dateideskriptoren zwischen Ihren Anwendungen übergeben müssen? Für andere Zwecke als Lernzwecke denke ich, dass es immer Möglichkeiten gibt, diese Beschränkung zu überwinden.

P.S. Sie serialisieren den Socket-Dateideskriptor unter Verwendung von QDataStream (als wäre es ein normaler int), dann senden Sie die serialisierten Daten für den anderen Prozess, um es auch als einen normalen int zu lesen. Dies ermöglicht es Ihnen, den ganzzahligen Wert des Dateideskriptors zu lesen, aber Sie werden nicht können Sie jede Interaktion damit zu tun, da Dateideskriptoren Werte sind nicht sinnvoll außerhalb des Prozesses sie gehören.