2017-05-12 8 views
1

Ich experimentiere mit einem sehr einfachen Apache Thrift-Server und Client in C++ mit Visual Studio 2015 geschrieben. Der Code basiert auf den offiziellen Apache Thrift-Beispielen.Apache Thrift-Server in C++ geschrieben löst TTransportException

Ich verwende die neueste Version von Thrift (0.10.0), Boost (1.64.0) und OpenSSL (1.1.0e).

Jeder Anruf vom Client zum Server löst eine TTransportException in TTransport.h Linie 43:

throw TTransportException(TTransportException::END_OF_FILE, "No more data to read."); 

Hier ist meine test.thrift Datei:

namespace cpp test 

service Test { 
    void ping() 
} 

Der thrift Compiler generiert Test.h Das ist unten sowohl im Server als auch im Client enthalten (es wird nicht der eigentliche Code angezeigt, da er automatisch generiert wird).

thrift Header-Dateien enthalten sowohl in Client und Server:

#include <thrift/protocol/TBinaryProtocol.h> 
#include <thrift/transport/TSocket.h> 
#include <thrift/transport/TTransportUtils.h> 
#include <thrift/server/TSimpleServer.h> 
#include <thrift/transport/TServerSocket.h> 
#include <thrift/transport/TBufferTransports.h> 

#include <Test.h> 

Client Haupt:

using namespace ::apache::thrift; 
using namespace ::apache::thrift::protocol; 
using namespace ::apache::thrift::transport; 
using namespace ::apache::thrift::server; 

using namespace std; 

int main() 
{ 
    boost::shared_ptr<TTransport> socket(new TSocket("localhost", 9090)); 
    boost::shared_ptr<TTransport> transport(new TFramedTransport(socket)); 
    boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); 
    test::TestClient client(protocol); 

    try { 
     transport->open(); 

     client.ping(); 
     cout << "ping()" << endl; 

     transport->close(); 
    } 
    catch (TException& tx) { 
     cout << "ERROR: " << tx.what() << endl; 
    } 
    return 0; 
} 

und Server Haupt:

using namespace ::apache::thrift; 
using namespace ::apache::thrift::protocol; 
using namespace ::apache::thrift::transport; 
using namespace ::apache::thrift::server; 

using namespace std; 

class TestHandler : virtual public test::TestIf { 
public: 
    TestHandler() { 
     // Your initialization goes here 
    } 

    void ping() { 
     // Your implementation goes here 
     printf("ping\n"); 
    } 
}; 


int main() 
{ 
    std::cout << "Starting thrift server thread" << std::endl; 
    int port = 9090; 
    boost::shared_ptr<TestHandler> handler(new TestHandler()); 
    boost::shared_ptr<TProcessor> processor(new test::TestProcessor(handler)); 
    boost::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port)); 
    boost::shared_ptr<TTransportFactory> transportFactory(new TFramedTransportFactory()); 
    boost::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); 

    boost::shared_ptr<apache::thrift::server::TSimpleServer> server = boost::shared_ptr< TSimpleServer>(new TSimpleServer(processor, serverTransport, transportFactory, protocolFactory)); 

    server->serve(); 
    return 0; 
} 

Ich habe auch versucht TBufferedTransport und TJSONProtocol mit mit das gleiche Ergebnis.

Die Tatsache, dass eine Ausnahme ausgelöst wird, zeigt an, dass dies nicht normal funktioniert, der Anruf jedoch empfangen und verarbeitet wird (die Ausnahme tritt nach dem Aufruf von TestHandler :: ping() auf) und der Server weiterhin zu hören und Empfangen von Anforderungen (jedes Mal den gleichen Fehler auslösen), so dass es eine wiederherstellbare Bedingung ist.

Also ich frage mich, warum das passiert, ist es etwas, das kann/sollte behoben werden, und wie, und wenn nicht, ist es sicher, den Server trotz dieser Ausnahme zu verwenden.

+0

Wird es am Serverende ausgelöst, wenn der Client die Verbindung schließt? – JensG

+0

Ja, meine Tests zeigen, dass das der Fall ist. Ich habe tatsächlich mehr Tests durchgeführt und ich fange an zu denken, dass dies das erwartete Verhalten ist, wenn der Client die Verbindung schließt, aber die Tatsache, dass es als Ausnahme signalisiert wird, hat mich verwirrt. Ich verstehe, dass eine Ausnahme ausgelöst werden sollte, wenn die Verbindung beispielsweise aufgrund eines Netzwerkfehlers geschlossen wird, aber dies ist ein kontrollierter und expliziter Aufruf von "close" und sollte wie erwartet vom Server gehandhabt werden. – Ady

+0

Ich stimme zu, das ist ein bisschen seltsam, aber ja, das ist der Fall. Ich habe mich immer gefragt, was der Grund für diesen Punkt im Design hätte sein können. Vielleicht ist es Zeit, das jetzt zu ändern. – JensG

Antwort

2

Durch Entwurf.

Thrift-Bibliotheken werden so implementiert, dass das Ende einer Verbindung intern signalisiert wird, indem ein TTransportException geworfen wird.

Verwandte Themen