Yasir Tahir Yasir Tahir - 2 months ago 55
Java Question

Connection lost (32109) - java.io.EOFException (MqttAndroidClient)

P.S. Please read the whole question before concluding anything.

I am getting the following exception whenever connect method is called:


Connection lost (32109) - java.io.EOFException
at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:146)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.io.EOFException
at java.io.DataInputStream.readByte(DataInputStream.java:77)
at org.eclipse.paho.client.mqttv3.internal.wire.MqttInputStream.readMqttWireMessage(MqttInputStream.java:65)
at org.eclipse.paho.client.mqttv3.internal.CommsReceiver.run(CommsReceiver.java:107)


I have tried couple of code snippets but both of them are raising the same exception.

Method 1

private final String serverUri = "tcp://95.177.135.232:9001";

private void mqqtConnectAndroidClient() {
String clientId = "clientID-" + MqttClient.generateClientId();
mqttAndroidClient = new MqttAndroidClient(getMainActivity(), serverUri, clientId);
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setKeepAliveInterval(60);
mqttConnectOptions.setCleanSession(true);
mqttConnectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);
try {
mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
subscribeToTopic();
}

@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
AppLog.Error("Failed to connect to: " + serverUri);
exception.printStackTrace();
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}


Method 2

private final String serverUri = "tcp://95.177.135.232:9001";

private void methodTwo() {
try {
MqttDefaultFilePersistence mdfp = new MqttDefaultFilePersistence(MQTT_DIR);
mqttClient = new MqttClient(serverUri, "1", mdfp);
MqttConnectOptions options = new MqttConnectOptions();
options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);
options.setKeepAliveInterval(60);
options.setAutomaticReconnect(true);
options.setCleanSession(true);
mqttClient.connect(options);
mqttClient.subscribe("#");
mqttClient.setCallback(new MqttCallback() {

@Override
public void connectionLost(Throwable arg0) {
AppLog.Error("Connection lost");
try {
mqttClient.connect();
} catch (MqttException e) {
e.printStackTrace();
}
}

@Override
public void deliveryComplete(IMqttDeliveryToken arg0) {
AppLog.Error("deliveryComplete");
}

@Override
public void messageArrived(String arg0, MqttMessage arg1) throws Exception {
AppLog.Error("messageArrived");
AppLog.Error(arg1.toString());
}
});
} catch (MqttException e) {
AppLog.Error("Main Exception");
e.printStackTrace();
}
}


Subscribe Method

public void subscribeToTopic() {
try {
String subscriptionTopic = "#";
mqttAndroidClient.subscribe(subscriptionTopic, 0, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
AppLog.Error("Subscribed!");
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
AppLog.Error("Failed to subscribe");
}
});
} catch (MqttException ex) {
System.err.println("Exception whilst subscribing");
ex.printStackTrace();
}
}


If I try the same server URI at HiveMQ, It is working perfectly fine with proper connection and subscription is also giving me results. I am using the following two libraries:


compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.0.2'


I tried some of the SO answers likes One, Two, Three, Four and Five but none of them are working for me.

Any help will be appreciated. Thank you in advance!

Answer

You are using port 9001 and the HiveMQ Link is pointing to a MQTT over Websockets client.

You are specifying a connection URI that starts with tcp:// which will signal to the service that it should connect with native MQTT not MQTT over Websockets.

As mentioned in the bug report for implementing Websocket support you need to start the connection URI with ws:// to let the client code know to use Websockets.