Java (重新)连接设备失败,出现订阅异常

Java (重新)连接设备失败,出现订阅异常,java,azure,Java,Azure,我正在使用azure iot设备SDK(1.3.31)连接模拟设备对于某些设备我在拨打此电话时遇到此异常: //pseudo code deviceInfo.device = registryManager.getDevice(deviceId); String deviceConnectionString = new StringBuilder() .append("HostName=").append(hubHostname)

我正在使用azure iot设备SDK(1.3.31)连接模拟设备对于某些设备我在拨打此电话时遇到此异常:

//pseudo code    
deviceInfo.device = registryManager.getDevice(deviceId);
String deviceConnectionString = new StringBuilder()
                .append("HostName=").append(hubHostname)
                .append(";DeviceId=").append(device.getDeviceId())
                .append(";SharedAccessKey=").append(device.getPrimaryKey())
                .toString();

DeviceClient deviceClient = new DeviceClient(deviceConnectionString, IotHubClientProtocol.MQTT);

deviceClient.open();
还有一个例外:

java.io.IOException: Unable to subscribe to topic :devices/sim3_0001/messages/devicebound/# because java.io.EOFExceptionConnection lost
    at com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttIotHubConnection.open(MqttIotHubConnection.java:142) ~[iot-device-client-1.2.30.jar:na]
    at com.microsoft.azure.sdk.iot.device.transport.mqtt.MqttTransport.open(MqttTransport.java:83) ~[iot-device-client-1.2.30.jar:na]
    at com.microsoft.azure.sdk.iot.device.DeviceIO.open(DeviceIO.java:212) ~[iot-device-client-1.2.30.jar:na]
    at com.microsoft.azure.sdk.iot.device.DeviceClient.open(DeviceClient.java:188) ~[iot-device-client-1.2.30.jar:na]
我对库代码做了一点挖掘,发现在订阅得到响应之前,我的连接已经断开了;这是已使用并转化为IOException的异常:

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:745)
Lost connection to the server. Reconnecting 0 time.
Caused by: java.io.EOFException
    at java.io.DataInputStream.readByte(DataInputStream.java:267)
    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)
此外,我还连接了iothub浏览器,查看是否获得了任何额外的有用信息。这就是它在我的公开电话中所说的:

    body: 
  protocol:      Mqtt
  authType:      { "scope": "device", "type": "sas", "issuer": "iothub" }
  time:          2017-06-13T21:13:48.2406702Z
  operationName: deviceConnect
  category:      Connections
  level:         Information
  deviceId:      sim3_0001
  ipAddress:     xx.xx.xxx.XXX
enqueuedTimeUtc:       Tue Jun 13 2017 17:13:53 GMT-0400 (EDT)
offset:                355136
applicationProperties: 
  category:      Connections
  level:         Information
  operationName: deviceConnect
sequenceNumber:        705
annotations: 
  x-opt-sequence-number: 705
  x-opt-offset:          355136
  x-opt-enqueued-time:   Tue Jun 13 2017 17:13:53 GMT-0400 (EDT)
offset:                355536
enqueuedTimeUtc:       Tue Jun 13 2017 17:13:53 GMT-0400 (EDT)
body: 
  protocol:          Mqtt
  authType:          { "scope": "device", "type": "sas", "issuer": "iothub" }
  time:              2017-06-13T21:13:48.3656729Z
  operationName:     deviceDisconnect
  category:          Connections
  level:             Error
  statusCode:        404
  statusType:        404104
  statusDescription: DeviceConnectionClosedRemotely
  deviceId:          sim3_0001
  ipAddress:         xx.xx.xxx.XXX
annotations: 
  x-opt-sequence-number: 706
  x-opt-offset:          355536
  x-opt-enqueued-time:   Tue Jun 13 2017 17:13:53 GMT-0400 (EDT)
applicationProperties: 
  category:      Connections
  level:         Error
  operationName: deviceDisconnect
sequenceNumber:        706

另一个注意事项:新设备成功连接/订阅,似乎它们在重新连接时更经常失败。如果我将打开的调用放入循环中,并在睡眠1秒后重试,设备最终会成功连接。

根据错误信息
java.io.IOException:无法订阅主题:devices/sim3_0001/messages/devicebound/#,因为java.io.eofeexception连接丢失
,我认为您试图通过订阅来接收云到设备的消息,使用
devices/{device_id}/messages/devicebound/#
作为主题过滤器。Azure官方文档的
小节将设备应用程序从AMQP迁移到MQTT
&
接收云到设备消息
,已将问题原因解释如下

接收云到设备消息

要从物联网中心接收消息,设备应使用
devices/{device_id}/messages/devicebound/#
作为主题过滤器进行订阅。主题筛选器中的多级通配符#仅用于允许设备接收主题名称中的其他属性。物联网中心不允许使用#通配符过滤子主题。由于IoT Hub不是一个通用的发布子消息代理,因此它只支持文档化的主题名称和主题过滤器


对于Azure IoT Hub,“MQTT不支持放弃/拒绝,因此我们将只显示从IoTHub收到的消息并返回完整信息”。GitHub上有一个官方文件,您可以参考它来更改代码并使其与MQTT一起工作。

真正的答案是,针对MQTT协议的azure iot hub设备库只允许每个应用程序一个连接。该库仅创建一个MQTT连接,因此如果您创建第二个设备并尝试连接其中一个设备,则将强制断开连接

有趣的是,如果我将协议更改为IoTubClientProtocol.AMQPS,一切都会按预期进行。我没有显式订阅任何内容,我只是调用DeviceClient.open方法,该方法订阅azure设备库中的该主题。有趣的是,它偶尔会起作用;如果我使用10个不同的设备启动10个连接,打开的调用中的5个或6个将成功。如果您查看device/transport/mqtt/MqttMessaging.java,您将看到一旦建立了连接,它将立即订阅该主题:this.subscribeTopic=“devices/”+deviceId+“/messages/devicebound/#”;你能再看看这个吗?这仍然是我们的问题!