오픈소스 MQTT Server(Mosquitto)와 WireShark를 활용하여 MQTT Control Packet을 자세히 바라보자.
상세 패킷을 분석하며 그림판에 직접 정리해보자.
1) 고정 헤더
: control packet type(7~4번 bit) + flags(3~0번 bit) + remaining length(7~0번 bit)
connect 타입의 value는 1 -> 0001, client -> server, 서버 연결 요청
flags = DUP(3번 bit) + QoS level(2~1번 bit) + RETAIN(0번 bit) -> connect는 flags가 0000으로 reserved
[1] DUP (Duplicate flag) :
0일 경우, 첫번째 전달 시도임을 의미하며,1일 경우에는 이전에 전달된 Packet이 재전송 Packet이라는 것을 의미한다. (QoS > 0)
[2] QoS : QoS 레벨
[3] Retain :1일 경우, 서버는 해당 Topic의 최종 내용을 저장하고 있다가 향후 구독하는 Client에게 이를 전달한다.
Msg Len = remaining length : 고정 헤더를 제외한 메시지의 나머지 부분의 길이가 12byte (가변헤더, 페이로드 포함)2) 가변 헤더
: protocol name, protocol version, connect flags, keep alive
protocol name length : MQTT 프로토콜 이름의 길이가 4byte
protocol name : 프로토콜 이름이 MQTT
version : MQTT 프로토콜 버전 3.1.1 = 프로토콜 버전 번호 4
connect flags = username(0) + password(1) + will retain(2) + QoS level(3~4) + Will(5) + Clean Session(6) + Reserved(7번 bit)
keep alive : 클라이언트의 최대 무활동 시간(초) = 60(default) -> 60초 동안 클라이언트가 데이터 전송을 하지 않으면 connection 연장을 위해 60초가 되는 시점에 PINGREQ 메시지를 보내어 연결이 유지되고 있음을 확인
PINGREQ와 PINGRES는 연결 확인을 위한 목적으로 사용되는데, 고정 헤더로만 구성되어 있다! MESSAGE TYPE의 VALUE는 각각 12와 13FLAGS는 0으로 예약됨REMAINING LENGTH = 0C0 00과 D0 00으로 주고 받는다3) 페이로드
: client id, will topic, will message, user name, password
client id : 클라이언트를 구분하는 고유 식별자, 따로 설정 X -> 길이가 0
client id가 지정되어 있다면, client id length 다음에 client id가 utf-8 encoding되어 나타난다.


1) 고정 헤더
: control packet type(7~4번 bit) + flags(3~0번 bit) + remaining length(7~0번 bit)
publish 타입의 value는 3 -> 0011, client <-> server, 발행flags = DUP(3번 bit) + QoS level(2~1번 bit) + RETAIN(0번 bit) -> publish는 flags 고정 XMsg Len = remaining length : 고정 헤더를 제외한 메시지의 나머지 부분의 길이가 9byte (가변헤더, 페이로드 포함)2) 가변 헤더
: topic, topic length, packet id(if QoS>0) (required)
topic length : 토픽 이름의 길이가 4bytetopic : 발행된 메시지가 할당된 토픽의 이름이 cook3) 페이로드
: application message (optional)
Message : 메시지 내용이 16진수로 표시됨, ASCII 값으로 변환하면 메시지의 내용을 알 수 있다!
1) 고정 헤더
: control packet type(7~4번 bit) + flags(3~0번 bit) + remaining length(7~0번 bit)
subscribe 타입의 value는 8 -> 1000, client <-> server, 서버 구독 요청flags = DUP(3번 bit) + QoS level(2~1번 bit) + RETAIN(0번 bit) -> subscribe는 0010으로 reservedMsg Len = remaining length : 고정 헤더를 제외한 메시지의 나머지 부분의 길이가 9byte (가변 헤더, 페이로드 포함)2) 가변 헤더
: packet id (required)
- 클라이언트가 특정 메시지 타입(
SUBSCRIBE,UNSUBSCRIBE,PUBLISH(QoS 1, 2),PUBREL,PUBREC,PUBCOMP)에서 사용되는 메시지의 순서를 추적하고 관리하기 위해 클라이언트 측에서 자동으로 생성하는 고유한 숫자- 일반적으로 Packet Identifier는 클라이언트가 처음 메시지를 전송할 때 자동으로 설정되며, 매 메시지마다 증가
Message identifier = packet id : subscribe 메시지의 패킷 식별자, 클라이언트가 메시지를 전송할 때 부여한 고유한 식별자, 브로커로부터 응답을 받을 때 이 식별자를 사용하여 구독 요청과 응답을 매칭 (여기서는 1로 설정됨)3) 페이로드
: topic length, topic, requested QoS
Topic Length : 토픽 이름의 길이가 4byte, 2바이트로 인코딩된다.Topic : 구독하고자 하는 토픽 이름 cook, 각 문자가 UTF-8로 인코딩되어 4바이트를 차지Requested QoS : 요청된 QoS 수준, 여기서는 "최소 한 번 이상 전달"을 의미하는 QoS 1이 요청되었다.







: Mosquitto 브로커는 기본적으로 클라이언트 간의 QoS 수준을 조정하고 처리할 수 있지만, 자체적으로 QoS 레벨을 설정하지는 않는다.
mosquitto.conf 파일을 통해 클라이언트가 사용할 수 있는 최대 QoS 수준을 설정할 수 있다!mosquitto.conf 파일의 max_qos 설정을 통해 클라이언트가 사용할 수 있는 최대 QoS를 제한하여 자원 관리 가능

PUBACK)을 받기 전까지 메시지를 메모리에 저장 gkekrk PUBACK 패킷을 받으면 메시지를 삭제PUBREC, PUBREL, PUBCOMP)를 통해 메시지가 정확히 한 번만 전달되도록 보장, 발행자는 브로커로부터 PUBCOMP 패킷을 수신한 후에 메시지를 삭제
ACK 응답을 수신한 후 메시지를 삭제COMP 패킷을 수신한 후에야 메시지를 삭제Clean Session = False로 설정되어 있다면, 브로커는 구독자가 오프라인 상태일 때도 해당 구독자의 QoS 1 또는 QoS 2 메시지를 저장Retain = True로 발행한 경우, 브로커는 해당 토픽에 마지막으로 발행된 메시지를 저장, 브로커에 저장된 Retain 메시지는 발행자가 새로운 Retain 메시지를 발행하거나 빈 메시지를 발행하여 Retain 메시지를 지우기 전까지 유지됨출처
- ChatGPT
- MQTT 프로토콜 분석 (1)
- MQTT 프로토콜 분석 (2)