paho.mqtt代码分析(有待详述)

MQTT与webSocket

Mqtt底层使用webSocket实现,通过发送http或https请求与服务端开始进行handshake,握手完成后协议将从http(https)升级成webSocket并建立长连,之后通过长连进行通信。sdk中关于websocket部分结构及handshake信息如下:

MQTT心跳包

分析心跳包首先看用于发送心跳信息的MqttPingReq.class和用于接收心跳答复的MqttPingResp.class

然后,我们需要从其发送的内容当中逆向推出其心跳包的内容。我 们先看其发送的的模块:找到public class CommsSender implements Runnable 类,看到其有一个private MqttOutputStream out;私有字段,一看这个方法,我们就能判断,这个字段就是输出流,打开public class MqttOutputStream extends OutputStream这个类,你会看到这样一个方法:

/**
    * Writes an <code>MqttWireMessage</code> to the stream.
    */
   public void write(MqttWireMessage message) throws IOException, MqttException {
      final String methodName = "write";
      byte[] bytes = message.getHeader();
      byte[] pl = message.getPayload();
//    out.write(message.getHeader());
//    out.write(message.getPayload());
      out.write(bytes,0,bytes.length);
      clientState.notifySentBytes(bytes.length);
      
        int offset = 0;
        int chunckSize = 1024;
        while (offset < pl.length) {
           int length = Math.min(chunckSize, pl.length - offset);
           out.write(pl, offset, length);
           offset += chunckSize;
           clientState.notifySentBytes(length);
        }     
      
      // @TRACE 500= sent {0}
       log.fine(CLASS_NAME, methodName, "500", new Object[]{message});
   }

原来,其发送的是header和payload,然后我们再看看心跳包的header和payload。

MqttPingReq和MqttPingResp中都有这么个方法:

protected byte[] getVariableHeader() throws MqttException {
   return new byte[0];
}

往上查看其共同父类MqttWireMessage.class中的getHeader():

public byte[] getHeader() throws MqttException {
    try {
        int first = ((getType() & 0x0f) << 4) ^ (getMessageInfo() & 0x0f);
        byte[] varHeader = getVariableHeader();
        int remLen = varHeader.length + getPayload().length;//长度为0

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        dos.writeByte(first);//写入一个字节
        dos.write(encodeMBI(remLen));//查看encodeMBI()方法实现可知此处也是只有一个字节
        dos.write(varHeader);//new byte[0]
        dos.flush();
        return baos.toByteArray();
    } catch(IOException ioe) {
        throw new MqttException(ioe);
    }
}
protected static byte[] encodeMBI( long number) {
   int numBytes = 0;
   long no = number;
   ByteArrayOutputStream bos = new ByteArrayOutputStream();
   // Encode the remaining length fields in the four bytes
   do {
      byte digit = (byte)(no % 128);
      no = no / 128;
      if (no > 0) {
         digit |= 0x80;
      }
      bos.write(digit);
      numBytes++;
   } while ( (no > 0) && (numBytes<4) );
   
   return bos.toByteArray();
}

而MqttWireMessage中还有一个getPayload方法,MqttPingReq和MqttPingResp都没有重写这个方法:

/**
 * Sub-classes should override this method to supply the payload bytes.
 */
public byte[] getPayload() throws MqttException {
   return new byte[0];
}

综合以上分析可知MQTT的心跳包实际只有2个字节,且第一个字

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值