paho.mqtt.android代码逐步分析(三)


声明:本文转载自https://my.oschina.net/u/3729361/blog/1607213,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

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个字节,且第一个字节中前4位表示消息类型后4位表示消息内容。

 

本文发表于2018年01月15日 12:35
(c)注:本文转载自https://my.oschina.net/u/3729361/blog/1607213,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2019 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1