最近在搞 PM2.5 採集,需要用到 MQTT 傳輸協議。協議部分看了幾天的,講的七七八八。本身在 intel 上有 寫好的MQTT 的源碼,現在的工作其實也就是移植到單片機上或者DM368板卡上。不過,對於之前沒有接觸過的我來說,還是從頭開始,搭建服務器及測試一下爲好。
MQTT服務器有好多種,參看:Servers/Brokers
Apache-Apollo:一個代理服務器,在ActiveMQ基礎上發展而來,可以支持STOMP、AMQP、MQTT、Openwire、SSL和WebSockets等多種協議,並且Apollo提供後臺管理頁面,方便開發者管理和調試。
EMQ:EMQ 2.0,號稱百萬級開源MQTT消息服務器,基於Erlang/OTP語言平臺開發,支持大規模連接和分佈式集羣,發佈訂閱模式的開源MQTT消息服務器。
HiveMQ:一個企業級的MQTT代理,主要用於企業和新興的機器到機器M2M通訊和內部傳輸,最大程度的滿足可伸縮性、易管理和安全特性,提供免費的個人版。HiveMQ提供了開源的插件開發包。
Mosquitto:一款實現了消息推送協議MQTT v3.1的開源消息代理軟件,提供輕量級的、支持可發佈/可訂閱的消息推送模式。
這篇文章我們只講兩種,一種是 Mosquitto、另一種是 Apollo,以及它們在 linux 下和 Windows 下的安裝。
我們本篇都會來一一做講解。
一、Ubuntu 下 MQTT 服務器搭建之Apollo
(1) 首先要搞清楚什麼是 Apollo
參看:ActiveMQ's next generation of messaging
ActiveMQ Apollo is a faster, more reliable, easier to maintain messaging broker built from the foundations of the original ActiveMQ. It accomplishes this using a radically different threading and message dispatching architecture. Like ActiveMQ, Apollo is a multi-protocol broker and supports STOMP, AMQP, MQTT, Openwire, SSL, and WebSockets.
翻譯一下:
ActiveMQ Apollo是從原始ActiveMQ的基礎構建的更快,更可靠,更易於維護的消息代理。 它使用完全不同的線程和消息調度架構來實現。 像ActiveMQ一樣,Apollo是一個多協議代理,支持STOMP,AMQP,MQTT,Openwire,SSL和WebSockets。
看到沒,有支持 MQTT
(2)安裝
先解壓
# sudo tar -zxvf apache-apollo-1.7.1-unix-distro.tar.gz
查看 bin/apollp.cmd
- # cat apollo.cmd
- @REM
- @REM Licensed to the Apache Software Foundation (ASF) under one or more
- @REM contributor license agreements. See the NOTICE file distributed with
- @REM this work for additional information regarding copyright ownership.
- @REM The ASF licenses this file to You under the Apache License, Version 2.0
- @REM (the "License"); you may not use this file except in compliance with
- @REM the License. You may obtain a copy of the License at
- @REM
- @REM http://www.apache.org/licenses/LICENSE-2.0
- @REM
- @REM Unless required by applicable law or agreed to in writing, software
- @REM distributed under the License is distributed on an "AS IS" BASIS,
- @REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- @REM See the License for the specific language governing permissions and
- @REM limitations under the License.
- @REM
- @echo off
- setlocal
- if NOT "%APOLLO_HOME%"=="" goto CHECK_APOLLO_HOME
- PUSHD .
- CD %~dp0..
- set APOLLO_HOME=%CD%
- POPD
- :CHECK_APOLLO_HOME
- if exist "%APOLLO_HOME%\bin\apollo.cmd" goto CHECK_JAVA
- :NO_HOME
- echo APOLLO_HOME environment variable is set incorrectly. Please set APOLLO_HOME.
- goto END
- :CHECK_JAVA
- set _JAVACMD=%JAVACMD%
- if "%JAVA_HOME%" == "" goto NO_JAVA_HOME
- if not exist "%JAVA_HOME%\bin\java.exe" goto NO_JAVA_HOME
- if "%_JAVACMD%" == "" set _JAVACMD=%JAVA_HOME%\bin\java.exe
- goto RUN_JAVA
- :NO_JAVA_HOME
- if "%_JAVACMD%" == "" set _JAVACMD=java.exe
- echo.
- echo Warning: JAVA_HOME environment variable is not set.
- echo.
- :RUN_JAVA
- set CLASSPATH=%APOLLO_HOME%\lib\apollo-boot.jar
- set BOOTDIRS=%APOLLO_HOME%\lib
- if NOT "x%APOLLO_BASE%" == "x" set BOOTDIRS=%APOLLO_BASE%\lib;%BOOTDIRS%
- if "%JVM_FLAGS%" == "" set JVM_FLAGS=-server -Xmx1G -XX:-UseBiasedLocking
- if "%APOLLO_ASSERTIONS%"=="false" goto noAPOLLO_ASSERTIONS
- set JVM_FLAGS=-ea %JVM_FLAGS%
- :noAPOLLO_ASSERTIONS
- if "x%APOLLO_OPTS%" == "x" goto noAPOLLO_OPTS
- set JVM_FLAGS=%JVM_FLAGS% %APOLLO_OPTS%
- :noAPOLLO_OPTS
- if "x%APOLLO_DEBUG%" == "x" goto noDEBUG
- set JVM_FLAGS=%JVM_FLAGS% -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
- :noDEBUG
- if "x%APOLLO_PROFILE%" == "x" goto noPROFILE
- set JVM_FLAGS=-agentlib:yjpagent %JVM_FLAGS%
- :noPROFILE
- if "%JMX_OPTS%" == "" set JMX_OPTS=-Dcom.sun.management.jmxremote
- rem set JMX_OPTS=-Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
- set JVM_FLAGS=%JVM_FLAGS% %JMX_OPTS%
- set JVM_FLAGS=%JVM_FLAGS% -Dapollo.home="%APOLLO_HOME%"
- if NOT "x%APOLLO_BASE%" == "x" set JVM_FLAGS=%JVM_FLAGS% -Dapollo.base="%APOLLO_BASE%"
- set JVM_FLAGS=%JVM_FLAGS% -classpath "%CLASSPATH%"
- "%_JAVACMD%" %JVM_FLAGS% org.apache.activemq.apollo.boot.Apollo "%BOOTDIRS%" org.apache.activemq.apollo.cli.Apollo %*
- :END
- endlocal
- GOTO :EOF
- :EOF
安裝 JDK
在linux終端輸入 getconf LONG_BIT 命令
如果是32位機器,則結果爲32
- [root@localhost ~]
- 32
- [root@localhost ~]
- 64
如果是64位機器,會輸出x86_64
- [chenzhou@testweb01 ~]$ uname -a
- Linux testweb01 2.6.18-308.4.1.el5 #1 SMP Tue Apr 17 17:08:00 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux
- [root@localhost ~]
- Linux localhost.localdomain 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:54 EDT 2009 i686 i686 i386 GNU/Linux
示例:32位機器
file /sbin/init
- [root@localhost ~]
- /sbin/init: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped
- [root@localhost ~]
- /bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped
file /sbin/init
- [chenzhou@testweb01 ~]$ file /sbin/init
- /sbin/init: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped
- [chenzhou@testweb01 ~]$ file /bin/ls
- /bin/ls: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped
- Linux ubuntu 3.2.0-23-generic-pae #36-Ubuntu SMP Tue Apr 10 22:19:09 UTC 2012 i686 i686 i386 GNU/Linux
- 32
sudo mkdir /usr/local/java
然後進入java目錄,命令行:cd /usr/local/java
sudo tar xvf jdk-8u25-linux-x64.tar.gz
設置jdk環境變量:
- 在最後添加下面代碼:
- export JAVA_HOME=/usr/local/java/jdk1.8.0_144
- export JRE_HOME=${JAVA_HOME}/jre
- export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
- export PATH=${JAVA_HOME}/bin:$PATH
- 使用 source /etc/profile 使它立即生效
- java version "1.8.0_144"
- Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
- Java HotSpot(TM) Client VM (build 25.144-b01, mixed mode)
配置 Apollo
cd apache-apollo-1.7.1/bin/
輸入 ./apollo 可以查看幫助
- # ./apollo
- usage: apollo [--log <log_level>] <command> [<args>]
- The most commonly used apollo commands are:
- create creates a new broker instance
- disk-benchmark Benchmarks your disk's speed
- help Display help information
- version Displays the broker version
- See 'apollo help <command>' for more information on a specific command.
- # ./apollo create mybroker
- Creating apollo instance at: mybroker
- Generating ssl keystore...
- You can now start the broker by executing:
- "/home/tarena/project/MQTT/apache-apollo-1.7.1/bin/mybroker/bin/apollo-broker" run
- Or you can setup the broker as system service and run it in the background:
- sudo ln -s "/home/tarena/project/MQTT/apache-apollo-1.7.1/bin/mybroker/bin/apollo-broker-service" /etc/init.d/
- /etc/init.d/apollo-broker-service start
啓動Apollo :
- # ./mybroker/bin/apollo-broker run
- _____ .__ .__
- / _ \ ______ ____ | | | | ____
- / /_\ \\____ \ / _ \| | | | / _ \
- / | \ |_> > <_> ) |_| |_( <_> )
- \____|__ / __/ \____/|____/____/\____/
- \/|__| Apache Apollo (1.7.1)
- Loading configuration file '/home/tarena/project/MQTT/apache-apollo-1.7.1/bin/mybroker/etc/apollo.xml'.
- INFO | OS : Linux 3.2.0-23-generic-pae (Ubuntu 12.04 LTS)
- INFO | JVM : Java HotSpot(TM) Server VM 1.8.0_144 (Oracle Corporation)
- INFO | Apollo : 1.7.1 (at: /home/tarena/project/MQTT/apache-apollo-1.7.1)
- INFO | OS is restricting the open file limit to: 100000
- INFO | Accepting connections at: tcp://0.0.0.0:61613
- INFO | Accepting connections at: tls://0.0.0.0:61614
- INFO | Starting store: leveldb store at /home/tarena/project/MQTT/apache-apollo-1.7.1/bin/mybroker/data
- INFO | Accepting connections at: ws://0.0.0.0:61623/
- INFO | Accepting connections at: wss://0.0.0.0:61624/
- INFO | Administration interface available at: https://127.0.0.1:61681/
- INFO | Administration interface available at: http://127.0.0.1:61680/
二、Windows 下 MQTT 服務器搭建之Apollo
(1)下載 Apollo
(2)安裝
(3)安裝 JDK
(4)創建服務器實例
etc:保存實例配置文件
data:保存用於存儲持久消息的數據文件
日誌:保存旋轉日誌文件
tmp:保存在代理運行之間安全刪除的臨時文件
三、MQTT 客戶端測試
四、Ubuntu 下 MQTT 服務器搭建之Mosquitto
(1)下載相關文件
(2)安裝編譯
《1》安裝 libwebsockets-2.0.2.tar.gz
《2》安裝
WITH_WEBSOCKETS:=no
爲
WITH_WEBSOCKETS:=yes
至此程序已經安裝完畢!
程序文件將默認安裝到以下位置
路徑 | 程序文件 |
/usr/local/sbin | mosquiotto server |
/etc/mosquitto | configuration |
/usr/local/bin | utility command |
由於操作系統版本及架構原因,很容易出現安裝之後的鏈接庫無法被找到,如啓動mosquitto客戶端可能出現找不到
libmosquitto.so.1文件,因此需要添加鏈接庫路徑
- 修正鏈接庫
- vim /etc/ld.so.conf.d/liblocal.conf
- /usr/local/lib64
- /usr/local/lib
修改mosquitto.conf文件
在 /etc/mosquitto/mosquitto.conf 的 Default Listener 一節添加如下幾行:
- # =================================================================
- # Default listener
- # =================================================================
- # IP address/hostname to bind the default listener to. If not
- # given, the default listener will not be bound to a specific
- # address and so will be accessible to all network interfaces.
- # bind_address ip-address/host name
- #bind_address
- # Port to use for the default listener.
- pid_file /var/run/mosquitto.pid
- user tarena
- port 1883
- max_connections -1
- allow_anonymous true
- listener 8080
- protocol websockets
下面測試時打開 mosquitto 會出現錯誤
# mosquitto -c /etc/mosquitto/mosquitto.conf
1502415109: mosquitto version 1.4.14 (build date 2017-08-07 15:54:10+0800) starting
1502415109: Config loaded from /etc/mosquitto/mosquitto.conf.
1502415109: Opening websockets listen socket on port 8080.
1502415109: Error: Unable to create websockets listener on port 8080.
解決方法:
(3)測試
《1》打開mosquitto
- # mosquitto -c /etc/mosquitto/mosquitto.conf
- 1502159482: mosquitto version 1.4.14 (build date 2017-08-07 15:54:10+0800) starting
- 1502159482: Config loaded from /etc/mosquitto/mosquitto.conf.
- 1502159482: Opening websockets listen socket on port 8080.
- 1502159482: Opening ipv4 listen socket on port 1883.
- 1502159482: Opening ipv6 listen socket on port 1883.
- -c,--config文件
- 從文件加載配置。 如果沒有給出,則使用mosquitto.conf(5)中描述的默認值。
- -d,--daemon
- 在後臺運行蚊子作爲守護進程。 所有其他行爲保持不變。
- -p,--port
- 在指定的端口上監聽,而不是默認的1883.除了配置文件中的端口設置外,還會起作用。 可以指定多次以打開在不同端口上偵聽的多個套接字。 該套接字將綁定到所有網絡接口。
- -v,--verbose
- 使用詳細日誌記錄。 這相當於在配置文件中將log_type設置爲全部。 這種覆蓋和記錄選項在配置文件中給出。
- 此時第一個終端多了一行信息
- 1502159482: mosquitto version 1.4.14 (build date 2017-08-07 15:54:10+0800) starting
- 1502159482: Config loaded from /etc/mosquitto/mosquitto.conf.
- 1502159482: Opening websockets listen socket on port 8080.
- 1502159482: Opening ipv4 listen socket on port 1883.
- 1502159482: Opening ipv6 listen socket on port 1883.
- 1502159601: New connection from 127.0.0.1 on port 1883.
- 1502159601: New client connected from 127.0.0.1 as mosqsub|2431-ubuntu (c1, k60)
- 下面的選項可以在命令行中給出,但也可以放置在位於$ XDG_CONFIG_HOME / mosquitto_sub或$ HOME / .config / mosquitto_sub的配置文件中,每行一對 - 吸附值。配置文件中的值將被用作默認值,並且可以通過使用命令行來覆蓋。這個例外是-t和-T,如果在配置文件中給出,將不會被覆蓋。還要注意,目前一些選項不能被否定,例如-S。具有#作爲第一個字符的配置文件行將被視爲註釋,不會進一步處理。
- -a
- 將輸出連接綁定到本地IP地址/主機名。如果需要將網絡通信限制在特定接口上,請使用此參數。
- -c,--disable-clean-session
- 禁用“'clean session”標誌。這意味着客戶端的所有訂閱將在斷開連接後維護,以及到達的後續QoS 1和QoS 2消息。當客戶端重新連接時,它將接收所有排隊的消息。如果使用此選項,建議使用 -id 手動設置客戶機ID
- --cafile
- 定義包含受信任的PEM編碼的CA證書的文件的路徑。用於啓用SSL通信。另請參見--capath
- --capath
- 定義包含受信任的PEM編碼的CA證書的目錄的路徑。用於啓用SSL通信。
- 爲了--capath正常工作,證書文件必須具有“.crt”作爲文件結束,您必須在每次添加/刪除證書時運行“c_rehash <path to capath>”。另請參見--cafile
- --cert
- 如果服務器需要,定義包含此客戶端的PEM編碼證書的文件的路徑。另請參閱--key。
- --ciphers
- 在客戶端支持的TLS密碼的openssl兼容列表。有關詳細信息,請參閱密碼(1)。
- -C
- 在接收到給定的消息數後立即斷開並退出程序。例如,在需要單個狀態值的shell腳本中這可能很有用。
- 結合-R來僅打印第一組新消息(即,沒有設置保留標誌),或者使用 -T 來過濾哪些主題被處理。
- -d,--debug
- 啓用調試消息。
- - help
- 顯示使用信息。
- -h,--host
- 指定要連接的主機。默認爲localhost。
- -i,--id
- 該客戶端使用的id。如果沒有給出,默認爲mosquitto_sub_附加客戶端的進程ID。不能與-id-prefix參數同時使用。
- -I,-id-prefix
- 通過追加客戶端的進程標識來提供客戶端ID的前綴。這在代理使用clientid_prefixes選項時很有用。不能與-id參數同時使用。
- --insecure
- 使用基於證書的加密時,此選項將禁用對服務器證書中服務器主機名的驗證。這在測試初始服務器配置時可能很有用,但是通過DNS欺騙可以讓惡意第三方冒充您的服務器。僅在測試中使用此選項。如果您需要在生產環境中使用此選項,則您的設置會出現故障,並且無需使用加密。
- -k,--keepalive
- 發送PING命令到經紀人以通知它之前的秒數仍然是連接和運行的。默認爲60秒。
- - key
- 如果服務器需要,定義包含此客戶端的PEM編碼私鑰的文件的路徑。另請參見--cert。
- -N
- 打印時,不要在有效負載上附加行尾符號。這允許將來自多個消息的有效載荷數據直接傳輸到另一個應用程序。只有在不使用-v的時候才真正有意義。
- -p,--port
- 連接到指定的端口而不是默認端口1883。
- -P, - pw
- 提供用於與經紀人進行認證的密碼。在不指定用戶名的情況下使用此參數是無效的。這需要一個支持MQTT v3.1的代理。另請參閱--username選項。
- - proxy
- 指定要連接的SOCKS5代理。支持“無”和“用戶名”身份驗證類型。 socks-url必須是形式socks5h:// [username [:password] @] host [:port]。協議前綴socks5h表示主機名由代理解析。符號%25,%3A和%40分別被URL解碼爲%,...和@,如果存在於用戶名或密碼中。
- 如果沒有給出用戶名,則不會嘗試認證。如果沒有給出端口,則使用默認值爲1080。
- 根據需求,將來可能會有更多SOCKS版本,並且將使用不同的協議前綴,如捲曲(1)所述。
- --psk
- 提供與代理使用的十六進制(無前導0x)預共享密鑰,以使用TLS-PSK加密支持。還必須提供--psk身份以啓用TLS-PSK。
- --psk身份
- 使用TLS-PSK支持的客戶端身份。這可以用來代替用戶名
- 此時第二個終端多了一行信息
- # mosquitto_sub -v -t test
- hello world
- 下面的選項可以在命令行中給出,但是也可以放置在位於$ XDG_CONFIG_HOME / mosquitto_pub或$ HOME / .config / mosquitto_sub的配置文件中,每行一對 - 吸附值。配置文件中的值將被用作默認值,並且可以通過使用命令行來覆蓋。這個例外是消息類型選項,其中只能指定一個。還要注意,目前一些選項不能被否定,例如-S。具有#作爲第一個字符的配置文件行將被視爲註釋,不會進一步處理。
- -a
- 將輸出連接綁定到本地IP地址/主機名。如果需要將網絡通信限制在特定接口上,請使用此參數。
- --cafile
- 定義包含受信任的PEM編碼的CA證書的文件的路徑。用於啓用SSL通信。另請參見--capath
- --capath
- 定義包含受信任的PEM編碼的CA證書的目錄的路徑。用於啓用SSL通信。
- 爲了--capath正常工作,證書文件必須具有“.crt”作爲文件結束,您必須在每次添加/刪除證書時運行“c_rehash <path to capath>”。另請參見--cafile
- --cert
- 如果服務器需要,定義包含此客戶端的PEM編碼證書的文件的路徑。另請參閱--key。
- --ciphers
- 在客戶端支持的TLS密碼的openssl兼容列表。有關詳細信息,請參閱密碼(1)。
- -d,--debug
- 啓用調試消息。
- -f,--file
- 發送文件的內容作爲消息。
- - help
- 顯示使用信息。
- -h,--host
- 指定要連接的主機。默認爲localhost。
- -i,--id
- 該客戶端使用的id。如果沒有給出,默認爲mosquitto_pub_附加客戶端的進程ID。不能與-id-prefix參數同時使用。
- -I,-id-prefix
- 通過追加客戶端的進程標識來提供客戶端ID的前綴。這在代理使用clientid_prefixes選項時很有用。不能與-id參數同時使用。
- --insecure
- 使用基於證書的加密時,此選項將禁用對服務器證書中服務器主機名的驗證。這在測試初始服務器配置時可能很有用,但是通過DNS欺騙可以讓惡意第三方冒充您的服務器。僅在測試中使用此選項。如果您需要在生產環境中使用此選項,則您的設置會出現故障,並且無需使用加密。
- -k,--keepalive
- 發送PING命令到經紀人以通知它之前的秒數仍然是連接和運行的。默認爲60秒。
- -key
- 如果服務器需要,定義包含此客戶端的PEM編碼私鑰的文件的路徑。另請參見--cert。
- -l,--stdin-line
- 發送從stdin讀取的消息,將單獨的行分成單獨的消息。請注意,空行不會被髮送。
- -m, - 消息
- 從命令行發送一條消息。
- -n, - 消息
- 發送null(零長度)消息。
- -p,--port
- 連接到指定的端口而不是默認端口1883。
- -P, - pw
- 提供用於與經紀人進行認證的密碼。在不指定用戶名的情況下使用此參數是無效的。這需要一個支持MQTT v3.1的代理。另請參閱--username選項。
- -proxy
- 指定要連接的SOCKS5代理。支持“無”和“用戶名”身份驗證類型。 socks-url必須是形式socks5h:// [username [:password] @] host [:port]。協議前綴socks5h表示主機名由代理解析。符號%25,%3A和%40分別被URL解碼爲%,...和@,如果存在於用戶名或密碼中。
- 如果沒有給出用戶名,則不會嘗試認證。如果沒有給出端口,則使用默認值爲1080。
- 根據需求,將來可能會有更多SOCKS版本,並且將使用不同的協議前綴,如捲曲(1)所述。
- --psk
- 提供與代理使用的十六進制(無前導0x)預共享密鑰,以使用TLS-PSK加密支持。還必須提供--psk身份以啓用TLS-PSK。
- --psk身份
- 使用TLS-PSK支持的客戶端身份。如果代理配置爲這樣做,則可以使用這可以替代用戶名。
- -q,--qos
- 指定消息的使用質量,從0,1和2.默認爲0。
- - quiet
- 如果給出此參數,則不會打印運行時錯誤。這排除了在無效用戶輸入的情況下給出的任何錯誤消息(例如使用 - 沒有端口的端口)。
- -r, - 保存
- 如果保留被賦予,則該消息將被保留爲經紀人的“最後已知的良好”值。有關更多信息,請參閱mqtt(7)。
- -s,--stdin-file
- 發送從stdin讀取的消息,將整個內容作爲單個消息發送。
- -S
- 使用SRV查找來確定要連接的主機。當我們執行查詢_mqtt._tcp