用 C++ 编写的 Apache Thrift 服务器抛出 TTransportException

Posted

技术标签:

【中文标题】用 C++ 编写的 Apache Thrift 服务器抛出 TTransportException【英文标题】:Apache Thrift server written in C++ throws TTransportException 【发布时间】:2017-05-12 00:19:36 【问题描述】:

我正在尝试使用 Visual Studio 2015 用 C++ 编写的非常简单的 Apache Thrift 服务器和客户端。代码基于官方 Apache Thrift 示例。

我正在使用最新版本的 Thrift (0.10.0)、Boost (1.64.0) 和 OpenSSL (1.1.0e)。

从客户端到服务器的每次调用都会触发 TTransport.h 第 43 行中的 TTransportException:

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

这是我的 test.thrift 文件:

namespace cpp test

service Test 
    void ping()

thrift 编译器生成 Test.h,它在下面的服务器和客户端中都包含在 #included 中(不显示实际代码,因为它是自动生成的)。

客户端和服务器都包含的thrift头文件:

#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>

客户端主:

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;

和服务器主:

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;

我也尝试使用 TBufferedTransport 和 TJSONProtocol 获得相同的结果。

抛出异常表明这不是正常运行,但是调用被接收和处理(异常发生在调用TestHandler::ping()之后)并且服务器继续监听和接收请求(每次触发相同的错误),所以它是一个可恢复的条件。

所以我想知道为什么会发生这种情况,是否可以/应该修复它,以及如何,如果没有,尽管有这个异常,使用服务器是否安全。

【问题讨论】:

客户端关闭连接时是否在服务端抛出? 是的,我的测试表明情况确实如此。事实上,我进行了更多测试,并且我开始认为这是客户端关闭连接时的预期行为,但它被标记为异常的事实让我感到困惑。我知道如果连接因网络错误而关闭,则应引发异常,但这是对“关闭”的受控且显式调用,应由服务器按预期行为进行处理。 我同意,这有点奇怪,但是是的,就是这样。我一直想知道设计中这一点的原因可能是什么。也许是时候改变它了。 【参考方案1】:

按设计。

Thrift 库以这种方式实现,其中通过抛出 TTransportException 在内部发出连接结束信号。

【讨论】:

以上是关于用 C++ 编写的 Apache Thrift 服务器抛出 TTransportException的主要内容,如果未能解决你的问题,请参考以下文章

Apache Thrift C++ typedef 问题

Apache Thrift C++ GlobalOutput 输出到哪里?

使用 Apache Thrift 的 Java 编译错误

Apache thrift“TProtocol 类”设计原理——C++,为啥需要“writeBool()”

Haskell Thrift 库在性能测试中比 C++ 慢 300 倍

Apache Thrift 和 ZeroMQ 的区别