簡體   English   中英

無法從Vert.x MQTT服務器接收消息

[英]Cannot receive messages from Vert.x MQTT Server

我正在嘗試使一些基於Paho的客戶端與Vert.x MQTT服務器一起使用。 我正在嘗試發布到我的接收客戶端已訂閱的測試主題。 我很難將消息從客戶發布者發送到客戶訂閱者。

使用我在Internet上看到的大量示例,我構建了一個MQTT Broker。 Vert.x MQTT Broker代碼的代碼如下:

public class MQTTBroker
{      
   public MQTTBroker()
   {
      MqttServerOptions opts = new MqttServerOptions();
      opts.setHost("localhost");
      opts.setPort(1883);

      MqttServer server = MqttServer.create(Vertx.vertx(),opts);

      server.endpointHandler(endpoint -> {
      System.out.println("MQTT client [" + endpoint.clientIdentifier() + "] request to connect, clean session = " + endpoint.isCleanSession());
      endpoint.accept(false);

      if("Test_Send".equals(endpoint.clientIdentifier()))
      {
         doPublish(endpoint);

         handleClientDisconnect(endpoint);
      }
      else
      {
          handleSubscription(endpoint);
          handleUnsubscription(endpoint);
          handleClientDisconnect(endpoint);
      }
     }).listen(ar -> {
      if (ar.succeeded()) {
           System.out.println("MQTT server is listening on port " + ar.result().actualPort());
       } else {
           System.out.println("Error on starting the server");
           ar.cause().printStackTrace();
       }
   });
 }

  protected void handleSubscription(MqttEndpoint endpoint) {
     endpoint.subscribeHandler(subscribe -> {
         List grantedQosLevels = new ArrayList < > ();
         for (MqttTopicSubscription s: subscribe.topicSubscriptions()) {
             System.out.println("Subscription for " + s.topicName() + " with QoS " + s.qualityOfService());
             grantedQosLevels.add(s.qualityOfService());
        }
        endpoint.subscribeAcknowledge(subscribe.messageId(), grantedQosLevels);
    });
}

protected void handleUnsubscription(MqttEndpoint endpoint) {
    endpoint.unsubscribeHandler(unsubscribe -> {
        for (String t: unsubscribe.topics()) {
            System.out.println("Unsubscription for " + t);
        }
        endpoint.unsubscribeAcknowledge(unsubscribe.messageId());
    });
}

protected void publishHandler(MqttEndpoint endpoint) {
     endpoint.publishHandler(message -> {
     endpoint.publishAcknowledge(message.messageId());
     }).publishReleaseHandler(messageId -> {
         endpoint.publishComplete(messageId);
     });
 }

protected void handleClientDisconnect(MqttEndpoint endpoint) {
    endpoint.disconnectHandler(h -> {
        System.out.println("The remote client has closed the connection.");
    });
}

protected void doPublish(MqttEndpoint endpoint) {

   // just as example, publish a message with QoS level 2
   endpoint.publish("Test_Topic",
     Buffer.buffer("Hello from the Vert.x MQTT server"),
     MqttQoS.EXACTLY_ONCE,
     false,
     false);
   publishHandler(endpoint);

   // specifing handlers for handling QoS 1 and 2
   endpoint.publishAcknowledgeHandler(messageId -> {

     System.out.println("Received ack for message = " +  messageId);

   }).publishReceivedHandler(messageId -> {

     endpoint.publishRelease(messageId);

   }).publishCompleteHandler(messageId -> {

     System.out.println("Received ack for message = " +  messageId);
   });
  }
}

我有一個Paho客戶端,應該從其訂閱的主題接收消息。 的代碼如下:

public class Receiver implements MqttCallback
{

   public Receiver()
   {     
      MqttClient client = null;

      try
      {
         MemoryPersistence persist = new MemoryPersistence(); 
         client = new MqttClient("tcp://localhost:1883",persist);
         client.setCallback(this);
         client.connect();
         client.subscribe("Test_Topic");
         System.out.println("The receiver is initialized.");
      }
      catch(Exception exe)
      {
         exe.printStackTrace();
      }
   }

   @Override
   public void connectionLost(Throwable arg0)
   {
      System.out.println("Connection is lost!");
   }

   @Override
   public void deliveryComplete(IMqttDeliveryToken arg0)
   {
      System.out.println("Delivered!");
   }

    @Override
   public void messageArrived(String theStr, MqttMessage theMsg)
   {
     System.out.println("Message from: "+theStr);

      try
      {
         String str = new String(theMsg.getPayload());
         System.out.println("Message is: "+str); 
      }
      catch(Exception exe)
      {
         exe.printStackTrace();
      }

   }

 }

訂閱者和發布者是本地的,盡管一旦我部署我的應用程序,它們就可以(並且將)與Broker保持遠程。 我用於發布的基於Paho的代碼如下:

public void publish(String theMsg)
{
   MqttClient nwclient = null;

   try
  {
      ServConfigurator serv = ServConfigurator.getInstance();
      MemoryPersistence persist = new MemoryPersistence(); 
      String url = "tcp://localhost:1883";

      nwclient = new MqttClient(url,"Test_Send",persist);

      MqttConnectOptions option = new MqttConnectOptions();
      option.setCleanSession(true);

      nwclient.connect(option);

      MqttMessage message = new MqttMessage(theMsg.getBytes());
      message.setQos(2);
      nwclient.publish("Test_Topic",message);

      nwclient.disconnect();
      nwclient.close();

   }
   catch(Exception exe)
   {
       exe.printStackTrace();
   }
}

請注意,我正在從代理發布硬編碼的字符串(出於測試目的)(如doPublish方法所示),盡管應注意的是,我正在捕獲發布者客戶端在端點處理程序中進行發布的嘗試。 不幸的是,盡管我可以毫無問題地將訂閱服務器和發布服務器連接到代理,但是由於某種原因,消息沒有到達訂閱服務器。 我已經嘗試了各種方法,但是盡管發布者客戶端實際上是發布給代理,但是由於某種原因,代理的發布未能將字符串發送給訂閱者。

我很確定我在這里遺漏了一些東西,但我無法想象它可能是什么。 誰能幫我使它正常工作???

在此先感謝您的幫助或見解。

當MQTT服務器接收到來自發布者的消息,從而使endpoint.publishHandler被調用以傳遞消息時,我在您的代碼中看不到任何邏輯來獲取主題並搜索為此主題注冊的訂戶(端點),並且向他們發送消息。 同時,我看不到您的代碼以某種方式保存了進行上述研究的訂戶端點和所訂主題之間的引用。 請記住,MQTT服務器不是代理,它不會為您處理有關主題的已訂閱客戶端列表。 您可以在此基礎上建立一個經紀人,這應該是您想做的事情?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM