【问题标题】:Solace Request-Response issues while using across platforms ( C# and JAVA )解决跨平台使用时的请求-响应问题(C# 和 JAVA)
【发布时间】:2016-01-22 14:57:17
【问题描述】:

我正在尝试在 Solace 中实现请求-响应。

但是 RR-Requestor 是用 C# 编写的,而 RR-Responder 的代码是用 JAVA 编写的。

我有 2 个问题:

  1. Solace C# API 成功发送消息后,它会被 JAVA 应用程序接收。我碰巧收到了 BytesXMLMessage 结构中的消息。 如何将消息转换为字符串? message.dump() 给了我全部的细节。

  2. 当我发送回复消息时,.NET 应用程序会收到带有一些额外不需要的字符的消息。

JAVA端使用的代码:

    //After session is created
    XMLMessageConsumer consumer = session.getMessageConsumer(new RequestHandler());
    XMLMessageProducer producer = session.getMessageProducer(new PrintingPubCallback());
    consumer.start();
    session.addSubscription(
            JCSMPFactory.onlyInstance().createTopic("Test_Response_Queue"),
            true);
    class RequestHandler implements XMLMessageListener {

    private void sendReply(BytesXMLMessage request, BytesXMLMessage reply)
            throws JCSMPException {

        producer.sendReply(request, reply);

    }

    public void onException(JCSMPException arg0) {
        // TODO Auto-generated method stub

    }

    public void onReceive(BytesXMLMessage message) {
        System.out.println("Received request message, trying to parse it");

        System.out.println(message.dump());

        try {

            TextMessage textMessage = JCSMPFactory.onlyInstance()
                    .createMessage(TextMessage.class);

            final String text = "Reply from JAVA, text message!!";
            textMessage.setText(text);

            sendReply(message, textMessage);

        } catch (JCSMPException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

在 .NET 方面

            // Create the request message
        IMessage requestMessage = ContextFactory.Instance.CreateMessage();
        requestMessage.Destination = ContextFactory.Instance.CreateTopic("Test_Response_Queue");
        requestMessage.DeliveryMode = MessageDeliveryMode.Direct; /* explicitly set to MessageDeliveryMode.Direct */
        //IStreamContainer stream = SDTUtils.CreateStream(requestMessage, 256);
        //stream.AddString("Hello from Linux!!");
        requestMessage.BinaryAttachment = Encoding.ASCII.GetBytes("Hello from Linux!!");

        // Send the request message to the service or RRDirectReplier
        IMessage replyMessage = null;
        int timeout = 2000; /* 2 secs*/
        Console.WriteLine("\nSending  request message, waiting for {0} msecs for a reply (make sure that RRDirectReply is running) ...", timeout);

        if (session.SendRequest(requestMessage, out replyMessage, 2000) == ReturnCode.SOLCLIENT_OK)
        {
            // Got a reply, format and print the response message
            Console.WriteLine("\nGot reply message");
            String str = Encoding.ASCII.GetString(replyMessage.BinaryAttachment);
            Console.WriteLine(str);
        }
        else
        {
            Console.WriteLine("Request failed");
        }
        if (requestMessage != null)
        {
            // It is a good practice to dispose of messages once done using them
            requestMessage.Dispose();
        }

回复在收到的字符串中包含其他字符。 见下图。

有什么想法吗?

谢谢。

【问题讨论】:

    标签: solace solace-mq


    【解决方案1】:

    有几种方法可以在不同 API 之间发送/接收字符串,这里有 2 种可能的方法。

    1。将字符串转换为字节数组,并将其作为二进制有效负载附加到 Solace 消息中。

    .NET 发送:

    IMessage message = ContextFactory.Instance.CreateMessage();
    message.Destination = topic;
    message.BinaryAttachment = Encoding.UTF8.GetBytes("My .NET String");
    session.Send(message);
    

    Java 接收:

    // assuming that message is a reference to a received message
    if(message.getAttachmentByteBuffer() != null) {
        byte[] messageBinaryPayload = message.getAttachmentByteBuffer().array();
        try {
            String myReceivedText = new String(messageBinaryPayload, "UTF-8");
            System.out.println("Received String = " + myReceivedText);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
    else {
        // No binary attachment in message - application needs to decide what to do next.
    }
    

    Java 发送:

    String myJavaString = "My Java String";
    BytesXMLMessage message = JCSMPFactory.onlyInstance().createMessage(BytesXMLMessage.class);
    message.writeAttachment(myJavaString.getBytes(Charset.forName("UTF-8")));
    producer.send(message, topic);
    

    .NET 接收:

    // assuming that message is a reference to a received message
    byte[] messageBinaryPayload = message.BinaryAttachment;
    
    if(messageBinaryPayload != null) {
        string myReceivedString = System.Text.Encoding.UTF8.GetString(messageBinaryPayload);
        Console.WriteLine("Received String = " + myReceivedString);
    }
    else {
        // No binary attachment in message - application needs to decide what to do next.
    }
    

    2。以 TextMessage 形式发送和接收字符串

    .NET 发送:

    IMessage message = ContextFactory.Instance.CreateMessage();
    message.Destination = topic;
    SDTUtils.SetText(message, "My .NET String");
    session.Send(message);
    

    Java 接收:

    // assuming that message is a reference to a received message
    if (message instanceof TextMessage) {
        String myReceivedString = ((TextMessage) message).getText();
        System.out.println("Received String = " + myReceivedString);
    } 
    else {
        // Message is not a TextMessage - application needs to decide what to do next.
    }
    

    Java 发送:

    TextMessage message = JCSMPFactory.onlyInstance().createMessage(TextMessage.class);
    message.setText("My Java String");
    producer.send(message, topic);
    

    .NET 接收:

    // assuming that message is a reference to a received message
    String myReceivedString = SDTUtils.GetText(message);
    if (myReceivedString != null) {
        // Message is an TextMessage
        Console.WriteLine("Received String = " + myReceivedString);
    }
    else {
        // Message is not a TextMessage - application needs to decide what to do next.
    }
    

    【讨论】:

    • 非常感谢@Russell Sim
    • 我也相信 if(session.SendRequest(requestMessage, out replyMessage, 4000) == ReturnCode.SOLCLIENT_OK){} 是发送消息的方式。它会等待 4 秒,等待回复消息到达。我们怎样才能让它无限期地等待呢?如果我们不确定 RRResponder 需要多长时间来响应。
    • @Dixit 没有办法让这个方法无限期地等待。您可以考虑使用巨大的超时值 (Int32.MaxValue) 来模拟无限期等待。但是,最好不要让您的应用程序无限期地等待,而是让它在一定时间后采取行动。也许是为了给用户一个通知?也许您可以考虑在等待一定时间后重新发送消息。
    【解决方案2】:

    如果您收到的消息是文本消息,请尝试以下操作:

    if (message instanceof TextMessage) {
        String text = ((TextMessage) message).getText();
    } 
    //otherwise retrieve the attachment buffer like this
    else {
        byte[] body = message.getAttachmentByteBuffer().array();
        //and convert to String
        String text = new String(body);
    }
    

    您可能会在回复消息的开头看到一个额外的字符,因为您正在创建一个 TextMessage 作为回复。 TextMessage 在附件的开头包含一些额外的字节以将其标记为 TextMessage 并且那些包含文本的长度。您应该在 .NET 中使用相应的类,例如为您进行解析的 TextMessage。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-23
      • 1970-01-01
      相关资源
      最近更新 更多