gpt4 book ai didi

java - 使用 TFramedTransport 时出现 TTransportException

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:47:36 25 4
gpt4 key购买 nike

我对这个问题很困惑。我有一个 Apache Thrift 0.9.0 客户端和服务器。客户端代码如下:

this.transport = new TSocket(this.server, this.port);
final TProtocol protocol = new TBinaryProtocol(this.transport);
this.client = new ZKProtoService.Client(protocol);

这很好用。但是,如果我尝试将传输包装在 TFramedTransport

this.transport = new TSocket(this.server, this.port);
final TProtocol protocol = new TBinaryProtocol(new TFramedTransport(this.transport));
this.client = new ZKProtoService.Client(protocol);

我在客户端收到以下模糊的(没有任何解释消息)异常。服务器端显示没有错误。

org.apache.thrift.transport.TTransportException
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:132)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:84)
at org.apache.thrift.transport.TFramedTransport.readFrame(TFramedTransport.java:129)
at org.apache.thrift.transport.TFramedTransport.read(TFramedTransport.java:101)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:84)
at org.apache.thrift.protocol.TBinaryProtocol.readAll(TBinaryProtocol.java:378)
at org.apache.thrift.protocol.TBinaryProtocol.readI32(TBinaryProtocol.java:297)
at org.apache.thrift.protocol.TBinaryProtocol.readMessageBegin(TBinaryProtocol.java:204)
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:69)
at com.blablabla.android.core.device.proto.ProtoService$Client.recv_open(ProtoService.java:108)
at com.blablabla.android.core.device.proto.ProtoService$Client.open(ProtoService.java:95)
at com.blablabla.simpleprotoclient.proto.ProtoClient.initializeCommunication(ProtoClient.java:411)
at com.blablabla.simpleprotoclient.proto.ProtoClient.doWork(ProtoClient.java:269)
at com.blablabla.simpleprotoclient.proto.ProtoClient.run(ProtoClient.java:499)
at java.lang.Thread.run(Thread.java:724)

如果我使用 TCompactProtocol 而不是 TBinaryProtocol,它也会失败。

在服务器端,我用自己的类扩展了 TProcessor,因为我需要为此客户端重用现有的服务处理程序(服务服务器端 IFace 实现):

@Override
public boolean process(final TProtocol in, final TProtocol out)
throws TException {
final TTransport t = in.getTransport();
final TSocket socket = (TSocket) t;
socket.setTimeout(ProtoServer.SOCKET_TIMEOUT);
final String clientAddress = socket.getSocket().getInetAddress()
.getHostAddress();
final int clientPort = socket.getSocket().getPort();
final String clientRemote = clientAddress + ":" + clientPort;
ProtoService.Processor<ProtoServiceHandler> processor = PROCESSORS
.get(clientRemote);
if (processor == null) {
final ProtoServiceHandler handler = new ProtoServiceHandler(
clientRemote);
processor = new ProtoService.Processor<ProtoServiceHandler>(
handler);
PROCESSORS.put(clientRemote, processor);
HANDLERS.put(clientRemote, handler);
ProtoClientConnectionChecker.addNewConnection(clientRemote,
socket);
}
return processor.process(in, out);
}

这就是我启动服务器端的方式:

TServerTransport serverTransport = new TServerSocket(DEFAULT_CONTROL_PORT);
TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(
serverTransport).processor(new ControlProcessor()));
Thread thControlServer = new Thread(new StartServer("Control", server));
thControlServer.start();

我有一些问题:

  • 重用服务处理程序实例是否正确,或者我不应该这样做?
  • 为什么当我使用 TFramedTransportTCompactProtocol 时会失败?如何解决这个问题?

欢迎就此问题提供任何帮助。提前致谢!

最佳答案

我遇到了同样的问题,终于找到了答案。可以在服务器上设置传输类型,尽管我在网上找到的大多数教程和示例中都不清楚这一点。查看 TServer.Args 类(或扩展 TServer.Args 的其他服务器的 args 类)的所有方法。有方法 inputTransportFactoryoutputTransportFactory。您可以使用 new TFramedTransport.Factory() 作为这些方法中的每一个的输入来声明服务器应该使用哪种传输。在 Scala 中:

  val handler = new ServiceStatusHandler
val processor = new ServiceStatus.Processor(handler)
val serverTransport = new TServerSocket(9090)
val args = new TServer.Args(serverTransport)
.processor(processor)
.inputTransportFactory(new TFramedTransport.Factory)
.outputTransportFactory(new TFramedTransport.Factory)
val server = new TSimpleServer(args)
println("Starting the simple server...")
server.serve()

请注意,如果您使用的是 TAsyncClient,则您无法选择所使用的传输方式。您必须使用 TNonblockingTransport,它只有一个标准实现,TNonblockingSocket,它在内部包装您在帧传输中使用的任何协议(protocol)。它实际上并没有将您选择的协议(protocol)包装在 TFramedTransport 中,但它确实将帧的长度添加到它写入的内容之前,并期望服务器也将响应的长度添加到前面。这在我找到的任何地方都没有记录,但是如果你查看源代码并尝试不同的组合,你会发现使用 TSimpleServer 你必须使用 TFramedTransport 来获取它与异步客户端一起工作。

顺便说一句,还值得注意的是,文档说 TNonblockingServer 必须在传输的最外层使用 TFramedTransport。但是,这些示例并未显示在 TNonblockingServer.Args 中进行了设置,但您仍然发现必须在客户端使用 TFramedTransport 才能在客户端成功执行 rpc服务器。这是因为 TNonblockingServer.Args 默认将其输入和输出协议(protocol)设置为 TFramedTransport(您可以使用反射来检查父类(super class)层次结构的字段或在源代码中看到这一点AbstractNonblockingServerArgs 的构造函数代码——您可以覆盖输入和输出传输,但服务器可能会因文档中讨论的原因而失败。

关于java - 使用 TFramedTransport 时出现 TTransportException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20149198/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com