连接Bridge后与MQTT交互抛出UnknownHostException如何解决?
问题背景
- 开发了一款支持MQTT操作、可与本地Bridge设备交互的应用,连接Bridge的方式和普通WiFi接入逻辑一致,即让移动设备通过WiFi直接接入Bridge的热点完成交互流程。
- 仅执行MQTT流程时,连接、订阅、发布数据、接收MQTT下行数据等所有MQTT相关操作均可正常运行。
- 完成Bridge交互流程后,再次尝试发起MQTT操作时抛出连接异常。
错误日志
MqttException (0) - java.net.UnknownHostException: Unable to resolve host "iot.rkl.com": No address associated with hostname 1608604152.272 9629-9629/com.asiczen.azlock W/System.err: at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38) 1608604152.272 9629-9629/com.asiczen.azlock W/System.err: at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:690) 1608604152.275 9629-9629/com.asiczen.azlock W/System.err: at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:75) 1608604152.275 9629-9629/com.asiczen.azlock W/System.err: at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:92) 1608604152.275 9629-9629/com.asiczen.azlock W/System.err: at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:676)
故障根因与修复方向
故障核心本质: 接入Bridge的专用WiFi热点后,该热点本身无公网出口、也不配置可解析公网域名的DNS服务,同时Android系统默认将该热点设为全局网络路由出口,导致解析公网MQTT broker域名时直接失败,抛出UnknownHostException。
- 修复方案1:与Bridge完成交互后,主动将设备默认网络切回可访问公网的原有WiFi/移动数据网络,再发起MQTT连接流程。
- 修复方案2:保持Bridge热点连接的同时,通过Android网络路由API强制将MQTT相关请求走具备公网出口的链路,不使用Bridge热点的默认DNS和路由规则。
- 修复方案3:提前将MQTT broker域名解析为固定IP并本地缓存,跳过Bridge热点下的DNS解析环节,直接通过IP发起连接。
核心业务代码片段
MQTT服务类实现
public class MqttMessageService extends Service { private static final String TAG = MqttMessageService.class.getSimpleName(); public static final String EXTRA_DATA = "android.nfc.extra.DATA"; public static final String MQTT_CONNECTED = "android.nfc.extra.MQTT_CONNECTED"; public static final String MQTT_DISCONNECTED = "android.nfc.extra.MQTT_DISCONNECTED"; public static final String MQTT_DATA_AVAILABLE = "android.nfc.extra.MQTT_DATA_AVAILABLE"; public static final String MQTT_DELEVIERY_COMPLETED = "android.nfc.extra.MQTT_DELEVIERY_COMPLETED"; public static final String MQTT_UNABLE_TO_PUBLISH = "android.nfc.extra.MQTT_UNABLE_TO_PUBLISH"; public static final String MQTT_UNABLE_TO_SUBSCRIBE = "android.nfc.extra.MQTT_UNABLE_TO_SUBSCRIBE"; public static final String MQTT_USUBSCRIBE = "android.nfc.extra.MQTT_USUBSCRIBE"; public static final String MQTT_UN_SCBSCRIBE = "android.nfc.extra.MQTT_UN_SCBSCRIBE"; private MqttAndroidClient mqttAndroidClient; public void connectMQTT(){ Log.d(TAG, "MQTT CONNECTION STAR: "); PahoMqttClient pahoMqttClient = new PahoMqttClient(); mqttAndroidClient = pahoMqttClient.getMqttClient(getApplicationContext(), Packet.PublishTopic.MQTT_BROKER_URL, AppContext.getClientId(this)); mqttAndroidClient.setCallback(new MqttCallbackExtended() { @Override public void connectComplete(boolean b, String s) { Log.d(TAG, "connectComplete: "); Log.d(TAG, "MQTT CONNECTED: "); broadcastUpdate(MqttMessageService.MQTT_CONNECTED); } @Override public void connectionLost(Throwable throwable) { Log.d(TAG, "connectionLost: "); Log.d(TAG, " MQTT CONNECTION LOST: "); broadcastUpdate(MqttMessageService.MQTT_DISCONNECTED); } @Override public void messageArrived(String s, MqttMessage mqttMessage) { String msg = new String(mqttMessage.getPayload(), StandardCharsets.ISO_8859_1); Log.d(TAG, "MQTT MESSAGE ARRIVED: "+msg); byte[] b = mqttMessage.getPayload(); broadcastUpdate(b); } @Override public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) { } }); } @Override public void onCreate() { super.onCreate(); Log.d(TAG, "onCreate"); Log.d(TAG, "MQTT ONCREATE: "); connectMQTT(); } private final IBinder mBinder = new LocalService(); @Override public IBinder onBind(Intent intent) { Log.d(TAG, "MQTT ONBIND: "); return mBinder; } @Override public boolean onUnbind(Intent intent) { Log.d(TAG, "MQTT ONUNBIND: "); return super.onUnbind(intent); } public class LocalService extends Binder { public MqttMessageService getService(){return MqttMessageService.this;} } public void subcribe(){ try { IMqttToken token = mqttAndroidClient.subscribe(Utils.getSubscribeTopic(), 0); token.setActionCallback(new IMqttActionListener() { @Override public void onSuccess(IMqttToken iMqttToken) { Log.d(TAG, "MQTT SUBSCRIBED 0: "); Log.d(TAG, "Subscribe Successfully " + "BridgeId_SCAN_RESPONSE"); broadcastUpdate(MqttMessageService.MQTT_USUBSCRIBE); } @Override public void onFailure(IMqttToken iMqttToken, Throwable throwable) { Log.e(TAG, "Subscribe Failed " + "BridgeId_SCAN_RESPONSE"); throwable.printStackTrace(); broadcastUpdate(MqttMessageService.MQTT_UNABLE_TO_SUBSCRIBE); } }); } catch (MqttException e) { broadcastUpdate(MqttMessageService.MQTT_UNABLE_TO_SUBSCRIBE); e.printStackTrace(); }catch (Exception e){ broadcastUpdate(MqttMessageService.MQTT_UNABLE_TO_SUBSCRIBE); e.printStackTrace(); } } public void msubscribe(String topic){ try { mqttAndroidClient.subscribe(topic, 0); Log.d(TAG, "MQTT SUBSCRIBED 1: "); } catch (MqttException e) { e.printStackTrace(); } } public void publish(byte[] payload){ Log.d(TAG, "publish: "); MqttMessage message = new MqttMessage(payload); message.setId(320); message.setRetained(false); message.setQos(0); try { mqttAndroidClient.publish(Utils.getPublishTopic(), message); Log.d(TAG, "MQTT DATA PUBLISHED: "); } catch (MqttException e) { e.printStackTrace(); broadcastUpdate(MqttMessageService.MQTT_UNABLE_TO_PUBLISH); }catch (Exception e){ e.printStackTrace(); } } public void unSubscribe(){ IMqttToken token; try { token = mqttAndroidClient.unsubscribe(Utils.getSubscribeTopic()); token.setActionCallback(new IMqttActionListener() { @Override public void onSuccess(IMqttToken iMqttToken) { Log.d(TAG, "UnSubscribe Successfully "); Log.d(TAG, "MQTT UNSUBSCRIBED: "); broadcastUpdate(MqttMessageService.MQTT_UN_SCBSCRIBE); } @Override public void onFailure(IMqttToken iMqttToken, Throwable throwable) { Log.e(TAG, "UnSubscribe Failed "); broadcastUpdate(MqttMessageService.MQTT_UN_SCBSCRIBE); } }); } catch (MqttException e) { broadcastUpdate(MqttMessageService.MQTT_UN_SCBSCRIBE); e.printStackTrace(); } } public void disconnect() { try { IMqttToken mqttToken = mqttAndroidClient.disconnect(); mqttToken.setActionCallback(new IMqttActionListener() { @Override public void onSuccess(IMqttToken iMqttToken) { Log.d(TAG, "MQTT DISCONNECTED: "); Log.d(TAG, "Successfully disconnect"); } @Override public void onFailure(IMqttToken iMqttToken, Throwable throwable) { Log.d(TAG, "Failed to disconnect " + throwable.toString()); } }); } catch (Exception e){ e.printStackTrace(); } } private void broadcastUpdate(final String action) { final Intent intent = new Intent(action); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } private void broadcastUpdate(byte[] data) { final Intent intent = new Intent(MqttMessageService.MQTT_DATA_AVAILABLE); intent.putExtra(EXTRA_DATA, data); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } }
Paho MQTT连接类实现
public class PahoMqttClient { public MqttAndroidClient getMqttClient(Context context, String brokerUrl, String clientId) { mqttAndroidClient = new MqttAndroidClient(context, brokerUrl, clientId); try { MqttConnectOptions MQTT_CONNECTION_OPTIONS = getMqttConnectionOption(); if (brokerUrl.contains("ssl")) { InputStream i= context.getResources().openRawResource(R.raw.client_ca); InputStream i1= context.getResources().openRawResource(R.raw.client_crt); InputStream inputStream = context.getResources().openRawResource(R.raw.client_key); MQTT_CONNECTION_OPTIONS.setSocketFactory(createSSLSocketFactory(i,i1,inputStream)); } IMqttToken token = mqttAndroidClient.connect(MQTT_CONNECTION_OPTIONS); token.setActionCallback(new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { mqttAndroidClient.setBufferOpts(getDisconnectedBufferOptions()); Log.d(TAG, "MQTT CONNECTED:0 "); Log.d(TAG, "Success"); } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.d(TAG, "MQTT CONNETION FAILED:0 "); exception.printStackTrace(); Log.d(TAG, "Failure " + exception.toString()); } }); } catch (MqttException e) { e.printStackTrace(); } return mqttAndroidClient; } }
内容的提问来源于stack exchange,提问作者Bichitra Pradhan
相关产品推荐
相关产品推荐

