MQTT Broker Client (3)

wldbs._.·2024년 9월 9일

MQTT

목록 보기
3/7
post-thumbnail

HandShaking

: 정보기술과 전기통신 및 관련 분야에서 채널에 대한 정상적인 통신이 시작되기 전에 두 개의 실체 간에 확립된 통신 채널의 변수를 동적으로 설정하는 자동화된 협상 과정, 채널의 물리적인 확립이 잇따르며, 정상적인 정보 전송 이전에 이루어진다.

  • 사람들이 처음 만났을 때 악수하듯이, 두 호스트가 서로 연결할 때에 필요한 정보들을 주고받는 일련의 과정들
  • TCP에서는 연결할 때 3-way Handshaking, 연결을 해제할 때 4-way Handshaking을 사용
  • 핸드세이킹에 필요한 TCP 세그먼트 내의 플래그(Flag)
    • SYN: Synchronize sequence number, 연결 시작 요청
    • ACK: Acknowledgement, 응답 확인
    • FIN: Finish, 연결 종료 요청

3-way Handshaking


클라이언트/서버 간의 연결을 수립할 때 사용되는 TCP 3 way Handshaking의 순서는 아래와 같다.
1. 클라이언트는 서버에게 접속을 요청한다. SYN
2. 클라이언트로부터 SYN 요청을 받은 서버는 클라이언트에게 요청을 수락한다 보낸다. SYN/ACK
3. 클라이언트가 서버에게 다시 ACK를 보내게 되면 연결이 이루어진 것이며, 실질적인 데이터가 오간다.


3-State

이때, 서버와 클라이언트는 신호를 주고받는 과정 속에서 '상태(State)'가 변하게 된다.

  • 먼저 클라이언트의 경우, 최초의 서버에게 SYN을 보낸 후, 서버로부터 다시 SYN/ACK를 받기 전까지 SYN-SENT 상태가 된다.
  • 서버의 입장에서는 클라이언트로부터 SYN을 받았을 때 SYN-RECEIVED 상태가 된다. 그리고 다시 클라이언트에게 SYN/ACK를 보낸다.
  • 서버로부터 SYN/ACK를 받은 클라이언트는 ESTABLISHED 상태가 된다. => '연결이 수립되었다'
  • 그리고 다시 서버에게 ACK를 보낸다. 그러면 ACK를 받은 서버도 ESTABLISHED 상태가 된다.

4-way HandShaking


클라이언트/서버 간의 연결을 해제할 때 사용되는 TCP 4 way Handshaking의 순서는 아래와 같다.
1. 클라이언트가 서버에게 종료 요청을 보낸다. FIN
2. 서버가 클라이언트의 종료 요청을 받아들인다. 그리고 그에 대한 응답을 보낸다. ACK ("일단 알겠다")
3. 서버는 연결을 종료할 준비가 끝나면 연결을 해제할 준비가 끝났다는 뜻으로 FIN을 클라이언트에게 보낸다.
4. 클라이언트는 서버로부터 FIN을 받을 것이며, 연결 해제의 준비가 끝났음을 확인했다는 뜻으로 다시 ACK를 보낸다.


4-State

  • FIN을 보낸 클라이언트는 FIN_WAIT 상태가 된다.
  • FIN을 받은 서버가 ACK을 보내고 나서 자신의 통신을 끝낼 때까지 CLOSE_WAIT 상태가 된다.
  • 연결 해제 준비가 끝난 서버가 클라이언트에게 FIN을 보내고, 이때 서버는 LAST_ACK 상태가 된다.
  • 서버로부터 FIN을 받은 클라이언트는 ACk를 보내는데 이때 TIME_WAIT 상태로 바뀌고, 이 ACK을 받은 서버는 CLOSED 상태가 된다.

서버에서 전송한 패킷이 문제가 발생하여 FIN보다 늦게 도착하는 상황이 발생할 수도 있다.
-> 이 때 FIN을 받은 클라이언트가 ACK를 보낸 직후 통신을 끊어버리면 그 데이터가 유실될 수 있다. 따라서 클라이언트는 서버로부터 FIN을 받은 후 일정 시간(Default : 240초) 동안 세션을 열어 두고, 잉여 패킷이 도착할 수 있도록 한다.

=> 즉 클라이언트는 TIME_WAIT 상태로 일정 시간 기다렸다가 CLOSED 상태로 바뀌게 되는 것이다.


QoS

"Quality of Service"의 약자로, 전달되는 Application Message의 신뢰성을 보장하는 레벨이다.

  • 0, 1, 2 총 3단계로 구분되며 숫자가 커질수록 높은 신뢰성을 보장하지만 그만큼의 리소스를 소모한다.
  • PUBLISH 제어 패킷에 포함되어 전송되며, MQTT는 이 규격을 사용하여 반드시 전달되어야 하는 메시지의 전달을 보장한다.

Client와 Server(Broker)는 각각 자신이 처리할 수 있는 최대 QoS 레벨을 가지고 있다.

  • 최대 QoS 레벨은 일반적으로 클라이언트와 서버가 지원하는 레벨에 따라 달라지며, 이는 각 MQTT 브로커의 구현이나 설정에 따라 결정된다.
  • 우선시 되는 것은 중심에 있는 Server의 QoS 레벨
    • 예를 들어, 클라이언트가 QoS 2로 메시지를 발행하더라도, 브로커가 QoS 1만 지원한다면, 메시지는 QoS 1로 처리
  • 클라이언트는 연결 시 자신이 처리 가능한 최대 QoS 레벨을 전송하며, 서버는 전송된 클라이언트의 QoS 레벨 중 자신이 수용 가능한 최대의 QoS 레벨을 선택하여 해당 클라이언트와의 메시지 송수신을 수행한다.

QoS 0: At most once delivery

최대 1번 전달을 보장하는 구조

  • 수신자(Broker)가 응답을 보낼 필요 X
  • 발신자(Publisher)는 수신자가 메시지를 제대로 받았는지 확인 X
  • 응답을 받지 않기에 발신자는 재전송 X
  • 수신자는 받은 메시지를 저장하지 않고 바로 구독자에게 발송
  • 메시지가 누락될 가능성 O -> 메시지는 0 or 1번 전달됨

Packet ID 없음: QoS 0에서는 메시지가 신뢰성 있는 전송을 보장하지 않기 때문에, 패킷 식별자(Packet ID)가 필요하지 않다!

  • Packet ID는 QoS 1과 QoS 2에서 메시지의 전달 상태를 추적하고 관리하는 데 사용

QoS 1: At least once delivery


최소 1번 이상의 메시지 전송을 보장하는 방식

  • 메시지 전송 시, 발신자(Publisher)는 Packet ID를 포함하여 보내고, 수신자(Broker)는 메시지를 받으면 메시지를 저장한 이후 구독자에게 메시지를 보내고 메시지를 삭제
  • 이후 메시지 수신 시 받은 Packet ID를 사용하여 PUBACK 메시지를 발신자에게 전송하면서 메시지 전달이 완료됨
  • 송신 측은 PUBACK 메시지로 수신 측이 메시지를 받았는지 확인 가능

다만, PUBACK 단계에서 네트워크 이슈 등으로 지연이 발생되었을 때 -> 발신자(Publisher)는 응답이 없기에 메시지를 재전송할 수 있다.

  • 이때 수신자가 메시지를 구독자에게 이미 발송하고 삭제한 상태라면, 수신자는 메시지 중복여부를 판별할 수 없기에 구독자에게 동일한 메시지를 다시 보낼 수 있다.
  • 이렇기에 QoS 1은 메시지가 미전송되는 상황은 막을 수 있으나, 메시지가 중복으로 전달될 가능성이 존재한다.

QoS 2: Exactly one delivery


가장 높은 QoS 레벨
: QoS 1에서는 발신자(Publisher)는 메시지 전송 후 응답을 받아 메시지 전송 성공여부를 판단
: QoS 2에서는 4-way HandShaking을 사용해 정확히 한번의 메시지 전송 보장

  • QoS 2에서 수신자(Broker)는 자신이 가지고 있는 메시지를 삭제하기 전에, 구독자에게 메시지를 전달했음을 발신자에게 알린다.
  • 이후 발신자에게 확인 메시지를 다시 받고 나서야 수신자는 자신이 저장하고 있는 메시지를 삭제
  • PUBREC 단계에서 지연이 발생해 발신자가 메시지를 재전송한다 하더라도, 수신자는 이전에 받은 메시지를 가지고 있기에 메시지를 구독자에게 재전송 X
  • 또한, PUBCOMP 단계에서 지연이 발생했다 하더라도 이미 이전에 PUBREC를 받음으로써 메시지를 구독자에게 보냈음을 확인했기에 구독자에게 메시지 재전송되는 상황 X

QoS 2는 처리에 소모되는 리소스가 크지만, 이러한 방식으로 정확히 1번 구독자가 메시지를 받게 되는 것을 보장한다.
-> 메시지 중복 전달 시 문제가 발생되는 데이터의 경우에 사용 가능

패킷 ID의 생성 및 관리:

  1. 동적 생성: 패킷 ID는 MQTT 클라이언트(발행자 또는 구독자)에 의해 동적으로 생성된다.
  • 일반적으로 패킷 ID는 순차적으로 증가하는 숫자를 사용하여 관리된다.
  1. 유니크한 ID: 각 패킷 ID는 활성 연결 내에서 유니크해야 한다.
  • 이는 메시지가 올바르게 추적되고 관리될 수 있도록 보장한다.
  1. 재사용: 일반적으로 패킷 ID는 메시지가 완전히 처리되고, 관련된 모든 확인 응답이 수신된 후에 재사용될 수 있다.

Topic Names and Topic Filters

MQTT 메시지의 발행과 구독은 Topic을 기준으로 이루어진다.
Topic은 Level Seperator(/)를 이용하여 아래와 같은 형태로 계층적으로 구성 가능하다.

Level Seperator로 구분된 각각의 계층은 Topic Level이라고 한다.


Topic Filter에서의 wildcard 사용

구독자는 Topic Filter를 사용하여 Topic을 구독한다.
Topic Filter에는 wildcard 문자가 포함될 수 있으며, 구독자는 이 wildcard 문자를 이용하여 다수의 Topic을 한 번에 Subscribe할 수 있디.
사용가능한 wildcard 문자와 의미를 알아보자.

1) # Multi Level wildcard
: 여러 단계의 Topic Level을 대체할 수 있다. 단독으로 쓰이거나 Topic Filter의 마지막 Level에 위치 가능하다.

2) + Single Level wildcard
: 한 단계의 토픽 레벨을 대체할 수 있다. 단독으로 쓰이거나 Topic Filter 내의 특정 Topic Filter에 위치 가능하다.


시스템 예약 Topic

Topic 중에는 $로 시작하는 특수 목적의 Topic이 있다.
이 Topic은 읽기 전용 Topic이며, 시스템에 의해 예약된 특수한 목적의 Topic이기에 클라이언트에서는 사용할 수 없다!

  • 기본적으로 제공되는 시스템 예약 토픽으로는 $SYS/ Topic이 있다.
  • $SYS/ Topic은 서버의 고유 정보를 모니터링하기 위해 사용된다.
  • $SYS/ 의 내용은 규격상 정해져 있지 않으며, 기본적인 지침은 있으며 아래와 같다.

Topic 작성 규칙

Topic Name과 Topic Filter는 작성 시 지켜여 할 기본적인 규칙들이 있으며, 내용은 아래와 같다.
1. Topic Name과 Topic Filter는 최소한 1글자보다 길어야 한다.
2. Topic Name과 Topic Filter는 대소문자를 구분한다.
3. 공백 문자의 사용은 가능하다.
4. Null (Unicode U+0000) 문자는 포함할 수 없다.
5. Maximum Topic 길이는 65535 bytes이다.
6. 앞, 뒤에 /가 붙으면 전혀 다른 Topic Name 혹은 Topic Filter가 된다.


Connect Flags

CONNECT 타입의 MQTT 제어 패킷의 경우, 'Connect Flags'라는 8bit(1Byte)의 정보가 Variable Header에 포함되어 있다.

8bit로 구성된 Flags 정보 내에는 아래와 같이 MQTT 연결과 관련된 각종 설정 값들이 기록되어 있다.

Clean Session

서버와 클라이언트는 안정적이 메시지 송/수신을 위해 Session 상태를 저장하고 있다.

Clean Session은 재연결 시, 이전 세션(Persistence session)을 사용할지를 설정하는 것이다.

  • 서버는 클라이언트가 Clean Session Flag를 0으로 설정하여 연결 요청을 하면 저장되어 있는 세션을 찾아 재활용하고,
  • 1로 설정하여 요청하면 신규 세션을 생성하여 사용한다.

또한 Clean Session 설정은 메시지 재전송 (Message delivery retry)과도 연관되어 있다.

  • QoS 레벨이 1, 2인 상황에서 클라이언트가 Clean Session 0으로 서버와 재연결되면, 클라이언트와 서버는 각각 응답을 받지 못한 패킷을 동일한 Packet ID로 재전송해야 한다.

Will Flag, Will QoS, Will Retain

MQTT에서 클라이언트는 자신이 접속 종료되었을 때 특정 Topic을 발송하라고 서버에 등록할 수 있다. 이것을 Will Message라고 한다.

  • Will Message를 사용하기 위해서는 Will Flag를 1로 설정하여 서버에 연결해야 한다.
  • 이렇게 하면 서버는 해당 클라이언트가 연결 종료되었을 때 모든 구독자들에게 Will Message를 발행하여 해당 클라이언트의 연결 상태를 전달한다.

Will Message 전송 시에도 QoS 레벨과 Retain 설정을 할 수 있으며, 이 값은 Connect Flags 내의 Will QoS, Will Retain에 설정된다.

  • Will Message 전송을 위한 Topic과 Message는 Payload에 포함된다.

User Name Flag, Password Flag

1로 설정될 경우, Payload에 User Name, Password 필드를 사용한다.

  • User Name Flag가 0이면 Password Flag도 0이다.
  • Payload의 User Name과 Password는 인증 및 권한 부여(Authentication and Authorization)를 위해 서버에서 사용될 수 있다.

Keep Alive

CONNECT 타입의 MQTT 제어 패킷에 포함되어 전달되는 정보이며, 16bit를 사용한다.

  • MQTT 프로토콜은 Keep Alive 필드를 이용하여 Keep Alive Interval을 설정한다.

기본적으로 클라이언트는 Keep Alive Interval이 지나기 전의 메시지 전송을 보장해야 한다.

  • 전송할 메시지가 없는 경우에도 클라이언트는 Connection 연장을 위해 메시지를 전달해야 하며
  • 이때 사용되는 제어 패킷이 PINGREQ, PINGRESP (클라이언트와 서버 간의 연결 상태를 유지하고 확인하기 위해 사용되는 제어 패킷)

PINGREQ (Ping Request)는 클라이언트가 서버에 보내는 패킷

  • 이 패킷은 클라이언트가 아직 활성 상태임을 서버에 알리며, 서버가 반응하도록 요구
  • 클라이언트는 설정된 keep-alive 시간 동안 어떠한 다른 MQTT 메시지도 서버에 보내지 않았을 때 PINGREQ를 보내서 연결이 여전히 유효한지를 확인

PINGRESP (Ping Response)는 서버가 PINGREQ를 받고 난 후 클라이언트에게 보내는 응답 패킷

  • 서버가 아직 활성 상태이며, 클라이언트의 PINGREQ를 성공적으로 수신했음을 알린다
  • 클라이언트는 이 PINGRESP를 받음으로써 서버와의 연결이 여전히 활성화되어 있고, 메시지 교환을 계속할 수 있음을 확인

서버는 Keep Alive 시간의 1.5배 내에 아무런 패킷이 들어오지 않으면 클라이언트와의 연결이 끊겼다고 판단하고, Will 메시지 전송 등의 절차를 수행할 수 있다.

  • Keep Alive 설정의 최대값은 65535초, 즉 18시간 12분 15초

출처: 블로그 + ChatGPT
MQTT란?
MQTT란 무엇인가?
HiveMQ
OSI 7계층
MQTT 프로토콜이란
MQTT 프로토콜 분석 (1)
MQTT 프로토콜 분석 (2)

profile
공부 기록용 24.08.05~ #LLM #RAG

0개의 댓글