2015-07-01 14 views
6

Eclipse Paho ile Java'da bir MQTT istemcisindeki bazı özellikleri uygulamaya çalışıyorum. Hedef, bir konuya abone olmak ve bir mesaj alındığında, müşteri başka bir konuya başka bir mesaj yollamaktır.Eclipse Paho kullanarak bir Java MQTT istemcisi alırken bir ileti nasıl yayınlanır

Bu çok kolay görünüyor, ama çözemediğim garip bir sorunum var. İşte benim kodum:

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; 
import org.eclipse.paho.client.mqttv3.IMqttToken; 
import org.eclipse.paho.client.mqttv3.MqttCallback; 
import org.eclipse.paho.client.mqttv3.MqttConnectOptions; 
import org.eclipse.paho.client.mqttv3.MqttException; 
import org.eclipse.paho.client.mqttv3.MqttMessage; 
import org.eclipse.paho.client.mqttv3.MqttClient; 
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; 

public class MqttOperations implements MqttCallback { 

    MqttClient sampleClient; 
    MqttConnectOptions connOpts; 

    public MqttOperations() { 
    } 

    public static void main(String[] args) throws InterruptedException { 
     new MqttOperations().launchMqttClient(); 
    } 


    public void launchMqttClient() throws InterruptedException { 
     try { 
       MemoryPersistence persistence = new MemoryPersistence(); 
       sampleClient = new MqttClient("tcp://broker.mqttdashboard.com:1883", "iamaclient", persistence); 
       connOpts = new MqttConnectOptions(); 
       connOpts.setCleanSession(true); 
       sampleClient.connect(connOpts); 
       sampleClient.subscribe("topic/example/ofmessage"); 
       sampleClient.setCallback(this); 

      } catch(MqttException me) { 
       System.out.println("reason "+me.getReasonCode()); 
       System.out.println("msg "+me.getMessage()); 
       System.out.println("loc "+me.getLocalizedMessage()); 
       System.out.println("cause "+me.getCause()); 
       System.out.println("excep "+me); 
       me.printStackTrace(); 
      } 
    } 


    @Override 
    public void connectionLost(Throwable cause) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void messageArrived(String topic, MqttMessage message) throws MqttException 
    { 
     System.out.println("Received: " + message.toString()); 
     try{ 
      System.out.println("Publishing message: i am the answer"); 
      MqttMessage ans = new MqttMessage("i am the answer".getBytes()); 
      ans.setQos(2); 
      sampleClient.publish("topic/example/ofanswer", ans); 
      System.out.println("Message published"); 

     }catch(MqttException me){ 
       System.out.println("reason "+me.getReasonCode()); 
       System.out.println("msg "+me.getMessage()); 
       System.out.println("loc "+me.getLocalizedMessage()); 
       System.out.println("cause "+me.getCause()); 
       System.out.println("excep "+me); 
       me.printStackTrace(); 
     } 

    } 

    @Override 
    public void deliveryComplete(IMqttDeliveryToken token) { 

    } 

} 

Sorun şu ki, bu program sadece bir kez çalışır. Mesaj alındığında, bu mesajın cevabı gönderilir, ancak "mesajın yayınlanması" mesajının ekranda hiç görüntülenmediği ve müşterinin başka mesaj almadığı görülür. Bu izlenimin, sampleClient.publish("topic/example/ofanswer", ans); hattının hiçbir zaman yürütme işlemini tamamlamadığını gördüm. Nasıl geldiğimi ve problemimi nasıl çözeceğimi bilen var mı?

+0

Diğer bir doğruluk: Kendi cevabımma cevap vermemeye dikkat etmem gerektiğini açıkladığı bazı kaynaklar buldum, aksi takdirde açıkça çalışamaz. Ama ben bu sorundan endişe duymuyorum çünkü yanıtlamak ve yayınlamak için kullandığım konular farklı – tben

+0

olduğunu düşünüyorum. Başka bir başlıkta yayınlamayı deneyebilir misiniz (örn. Bir Executor kullanın ve sadece MessageArrived geri aramada bir yayınlama komutu gönderin)? –

cevap

2

Bugün benzer bir sorun yaşadım. an other question with two connections okunduğumda anladım: İki MqttClient örneğine ihtiyacınız var. Bir yayıncılık ve bir abone için. Maalesef bu gerçek için bir doküman bulunamadı.

Bu arada. İlk uygulamamda iki müşteri ile, onlara aynı kimlikleri verdim (mantıksal olarak aynı bağlantı olmalı). Ancak ikinci bağlantı ilkini keser. İki farklı kimlik kullanmaya başladığımda çalışmaya başlar.

+0

Gerçekten bana yardımcı oldu. :) –

+0

Bu mesaj, ileti varlığınız için http://www.eclipse.org/paho/files/javadoc/index.html dosyasını okuduysanız, iki bağlantıya sahip olmanız gerekmediği için beni rahatsız ediyor. çok tezahürat çalışıyor! – Clocker

0

Dominik Obermaier haklı: Sorun mesajla engellendiniz. Özellikle, MqttClient.publish, iletinin teslim alındığına dair bir bildirim gelene kadar bekler - ancak MqttClient iş parçacığı onu almaz, çünkü MessageArrived'deki bildirimi beklerken oturmaktadır!

İki istemcinin çözümü, diğer istemcinin iş parçacığı, bildirimi yuvadan almakta özgür olduğu için işe yarıyor, ancak uygun çözüm, QoS 0 ile mesajın içinden yayınlanmaktır (QoS 0 iletilerinin teslimat onayı gerekmez)) veya MqttTopic.publish gibi iletinin teslim edilmesini beklemeyen bir API kullanın.