본문 바로가기

Etc..

실전 MQTT - MQTT Protocol 의 구조에 대해서

MQTT를 통해 데이터를 주고 받기 위해선 버퍼에 바이트 데이터를 실어서 보낼수 있어야 한다.

데이터 통신에 대해서 알고 있다면 정말 좋다.

설명을 위해 사용된 Buffer는  Nodejs 의 Buffer를 이용하였다. 여기에서 선언되어 있는 Buffer 는 배열로도 데이터를 보낼수 있다.

MQTT Protocol 의 명세이다.

http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html


2. Message format

The message header for each MQTT command message contains a fixed header. Some messages also require a variable header and a payload. The format for each part of the message header is described in the following sections:


MQTT 의 메세지 형식이다.

MQTT는 크게 3가지 부분으로 이루어져있다.

Fixed Header, Variable Header, 메세지를 담을수 있는 Payload 라는 것으로 나누어져 있는것을 알수 있다.


MQTT Protocol 명세에서 자세하게 설명되어 있다.

필자는 간략하게 명세서의 테이블을 읽는 방법에 대해서만 설명하도록 하겠다.

Nodejs 의 Buffer는 배열로도 사용할수가 있다. 간단하게 설명서 대로 맞는 위치에 배열에 값만 넣어주면 된다.


Fixed header의 구조이다.


2바이트로 이루어져 있으면 1바이트 영역에 메세지 타입 DUP flag Qos level RETAIN 이 들어가고 2번째 바이트에는 Variable header 와 payload 의 길이를 더한값을 넣어줘서 메세지 의 정보를 넣어준다. 즉 Fixed header 외의 다른 header 정보를 넣어주는 것이다.

MQTT 명세를 읽어보면 각 Message Type 에 대해서 정의해 놓은 부분이 있다.

Publish 3

Disconnect 14

(1바이트는 8비트로 이루어져 있다.  이것을 반으로 나눠서 1248로 보면 이해하기 쉽다.)


이렇게 나눠서 Bitwise Operation 을 해주면 되는것이다.

메세지 명세를 통해 알게된 PUBLISH 의 메세지 타입은 3이었다.

이것을 실제 버퍼에 넣는다고 하면

var FixedHeader[0] = 0x30 이 된다. 이렇게 선언하게 되면 메세지는 PUBLISH 이고 나머지 DUP flag나 QOS level , RETAIN 은 없는 것이라고 명시한것이 된다.


Variable header

Fixed header 와 Payload 사이에 존재하며.. 이 헤더는 각 기능에 따라 조금씩 달라지기 때문에 PUBLISH 를 통해 설명 하도록 하겠다.

payload의 메세지 크기 와 같은 정보를 담고 있다고 생각하면 된다.


Payload

MQTT의 메세지 형식은 기본적으로 UTF-8 로 되어 있다.

payload의 경우에도 

var payload[0] = String Length MSB의 정보를 넣어준다 Variabel header에서 메세지의 형식이 MSB가 아니라면 0 이 들어가면 된다.

payload[1] = String Length LSB의 정보를 넣어준다. MSB의 경우 MQTT의 특성상 과연 많이 사용될까 싶긴하지만.. 많들어놨으니 어쩔수 없다.

payload[메세지 size] = 실제로 넘겨 받은 Topic 과 메세지를 한 바이트에 한 글자씩 넣어주는 부분이다.


이렇게 만들어진 헤더들을 하나로 만들어서, 아니면 처음부터 각 사이즈를 다 계산한뒤 버퍼에 넣어줘도 된다.

메세지를 보내면 (Nodejs 의 버퍼는 conn.write(buffer)로 보낼수 있다.) 데이터가 전송되는것을 확인할수 있다.


Putty와 같은 터미널에서 확인해보고자 한다면


1
2
3
4
5
var bytes = new Uint8Array(buffer);
 
for(var i=0; i<bytes.byteLength; i++){
   sys.puts('buffer = '  + String.fromCharCode(bytes[i]));
}


로 확인가능하다.