code/protocol

Docker MQTT 통신 C++

인간도피자 2024. 1. 26. 16:24

이번에는 C++ 로 통신 구현!

1. 컨테이너 열 때 포트포워딩 필수! (이건 전 포스팅에 쓰여있음)

2. 파일 구성은 이런 식. 이게 뭐야! 싶겠지만 컨테이너 열어서 build 폴더 하나만 만드시고 아래 따라하면 됩니다.

벌써 끄고 싶어지는 아찔한 풍경

 

3. 일단 통신이 되는 CPP 기본 소스! (main.cpp)

코드 설명은 안 할 거고 중요한 건 포트포워딩할 때 포트 번호, 현재 호스트 IP 주소, 토픽 이름입니다. 포트 번호는 컨테이너를 열었을 때 포워딩한 번호, IP 주소는 로컬, 토픽 이름은 나중에 MQTT를 연결할 때 사용하니 임의로 적으셔도 무방.

#include <mosquitto.h>
#include <cstdio>
#include <cstring>
#include <unistd.h>

#define mqtt_host "127.0.0.1"
#define mqtt_port 1883
#define keep_alive 60

int main(int argc, char **argv)
{
  mosquitto_lib_init();
  struct mosquitto *mosq = mosquitto_new(NULL, true, NULL); 

  if(mosq)
  {
   
    if(mosquitto_connect(mosq, mqtt_host, mqtt_port, keep_alive) != MOSQ_ERR_SUCCESS)
    {
      fprintf(stderr, "Unable to connect.\n");
      return -1;
    }



    while(true){
        const char *msg = "Hello, MQTT!";
        int ret = mosquitto_publish(mosq, NULL, "cpp/test", strlen(msg), msg, 0, false);
        
        if(ret != MOSQ_ERR_SUCCESS)
        {
        fprintf(stderr, "Failed to publish message: %s\n", mosquitto_strerror(ret));
        }
        else
        {
        printf("Message published successfully\n");
        }
        sleep(5);
    }
   

    mosquitto_disconnect(mosq);
    mosquitto_destroy(mosq);
  }
  else
  {
    fprintf(stderr, "Failed to create mosquitto instance.\n");
  }

  mosquitto_lib_cleanup();

  return 0;
}

 

4. CMakeLists 파일 생성 (CMakeLists.txt)

그냥 복붙하되 project 이름은 바꿔줄 수 있습니다.

cmake_minimum_required(VERSION 3.0)
project(MosquittoClientExample)

find_package(PkgConfig REQUIRED)
pkg_search_module(MOSQUITTO REQUIRED libmosquitto)

add_executable(mqtt_client main.cpp)

target_link_libraries(mqtt_client ${MOSQUITTO_LIBRARIES})
target_include_directories(mqtt_client PUBLIC ${MOSQUITTO_INCLUDE_DIRS})

 

5. 그리고 cpp, cmakelists를 만들어 준 바로 그 경로에 build 파일 만드세요.

mkdir build
cd build

 

6. build 

근데 이렇게 빌드하다가 막히는 사람 분명 있을 겁니다. 

cmake ..
cmake --build .

그럼 아래 중에 골라서 해결하세요. 완전 친절하다. 인정~

# 1. 공통
sudo apt-get update

# 2. cmake 문제일 시
sudo apt-get install cmake

# 3. pkg-config 문제일 시 
sudo apt-get install pkg-config

# 4. mosquitto-dev 문제일 시
sudo apt-get install libmosquitto-dev

# 4-1. 4번이 안 될 시
sudo apt-get update -y
sudo apt-get install -y libmosquitto-dev

 

7. mosquitto broker 실행

mosquitto -v

 

8. 코드 실행

위 7번을 실행했으면 console 창이 mosquitto log가 찍혀서 안 될 텐데 그땐 쿨하게 새 탭 열어서 docker 중복 접속으로 하세요. 백그라운드 실행하는 방법이 있으면 나도 알려주고. (귀찮으니까)

# 이건 cmake 이름을 바꾸면 달라질 수 있음
# ls 하여 실행 파일 이름 확인해서 실행하세요

./mqtt_client

 

9. subscribe 해서 확인

이건 전 포스팅처럼 MQTT Explorer를 이용해서 확인합니다. 똑같은 설정인데 캡쳐하기 귀찮으니까 설정 손댄 부분만 이야기하면
* Host = Docker 연 Linux PC의 IP (나는 192.168.40.128)
* Port = Container 열 때 포워딩한 Port (51005:1883이면 51005. 1883은 Publish할 때 씀. 나는 51005였음)
* ADVANCED 클릭하여 topic 추가 (Cpp 코드에 사용한 topic 넣으면 됨)

 

+ 추가

10. subscribe에서 access denied가 뜬다. 그러면 mosquitto -v 할 때 아래 뜨는 log에서 Starting in local only mode인지 아닌지 확인해야 된다. 이때 local mode로 돼 있으면 container 안에서만 통신이 되고 바깥으로는 통신이 안 된다. 접근도 안 되는 듯하다. 

해결 방법은 docker 내부에 있는 mosquitto.conf 파일을 찾아 접근할 수 있도록 수정하는 것이다. 아래 명령어를 복사해 붙이면 된다.

find / -name mosquitto.conf 2>/dev/null

그러면 어디에 있는지 뜨기 때문에 cd를 통해 접근하고 수정하면 된다. 추가할 코드는 아래와 같다.

listener 1883 0.0.0.0
allow_anonymous true

추가했으면 저장. 저장한 다음에는 원래 사용했던 mosquitto -v가 아니라 다른 명령어를 통해서 실행한다.

mosquitto -c mosquitto.conf -v

이 명령어를 통해서 실행하지 않으면 local mode로 실행되고, mosquitto.conf 파일이 적용되지 않는 듯하다. 이 명령어를 통해 실행한 다음에 다시 mqtt publish를 시작하면 외부에서 접근이 가능하다.