版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010277446/article/details/88059670
之前在前端网页上写一个小网站,用于开发时在线订阅、发送mqtt数据包。
当部署在线上服务器时,因为域名网页有加载Https证书,所以连接mqtt时只能选用wss方式,却没有成功连接上mqtt。而mqtt的ws连接方式是可以的。
一、服务端配置
1.mqtt的配置文件
先来看线上服务器中mqtt配置文件
port 1883
listener 61613
protocol websockets
配置中,1883是tcp连接, 61613是ws连接方式
2.nginx配置方案
采用的方案是,在nginx中配置wss支持,再反向代理转至mqtt的ws连接端口,实测这样配置后mqtt是可以在https网页中通过wss正常连接、收发数据等。
# 先定义一个upstream分发到ws,此处反向代理或做负载均衡
upstream mqttServer {
server localhost:61613;
}
# 配置wss支持
location /mqttwss {
proxy_set_header Host $http_host;
proxy_pass http://mqttServer;
proxy_http_version 1.1;
proxy_set_header X-Client-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300s; # 默认是60秒,可设置
}
二、前端wss连接
选择 Eclipse Paho JavaScript Client 连接库
utility.js
/*
Eclipse Paho MQTT-JS Utility
This utility can be used to test the Eclipse Paho MQTT Javascript client.
*/
// Create a client instance
client = null;
connected = false;
// called when the client connects
function onConnect(context) {
// Once a connection has been made, make a subscription and send a message.
alert("连接成功: \nHost: " + context.invocationContext.host + ':' + context.invocationContext.port + context.invocationContext.path + ' \nClientID: ' + context.invocationContext.clientId);
connected = true;
}
function onFail(context) {
alert("连接失败: " + context.errorMessage);
connected = false;
}
// called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
alert("连接已断开,请重新连接: " + responseObject.errorMessage);
}
connected = false;
}
// called when a message arrives
/*called when a message arrives
* @message: 收到消息
*/
function onMessageArrived(message) {
alert('Message Recieved: \nTopic: '+message.destinationName+'\nPayload: '+message.payloadString+'\nQoS: '+message.qos);
// alert(message);
var messageTime = new Date().toISOString();
// pare message
// alert('Topic:' + message.destinationName);
// alert('Payload:' + safe_tags_regex(message.payloadString));
// alert('messageTime:' + messageTime);
// alert('QoS:' + message.qos);
}
/*连接*/
function connect(clientId){
var hostname = 'mqtt.example.cn';
var port = 61613;
// var clientId = 'msg_publisher_1';
var path = '/mqttwss';
var user = 'username';
var pass = 'password';
var keepAlive = 90;
var timeout = 3;
var tls = true;
var cleanSession = false;
var lastWillTopic = '/test/will/' + clientId;
var lastWillQos = 1;
var lastWillRetain = false;
var lastWillMessage = 'net offline';
if(path.length > 0){
client = new Paho.MQTT.Client(hostname, port, path, clientId);
} else {
client = new Paho.MQTT.Client(hostname, port, clientId);
}
// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
var options = {
invocationContext: {host : hostname, port: port, path: client.path, clientId: clientId},
timeout: timeout,
keepAliveInterval:keepAlive,
cleanSession: cleanSession,
useSSL: tls,
onSuccess: onConnect,
onFailure: onFail
};
if(user.length > 0){
options.userName = user;
}
if(pass.length > 0){
options.password = pass;
}
if(lastWillTopic.length > 0){
var lastWillMessage = new Paho.MQTT.Message(lastWillMessage);
lastWillMessage.destinationName = lastWillTopic;
lastWillMessage.qos = lastWillQos;
lastWillMessage.retained = lastWillRetain;
options.willMessage = lastWillMessage;
}
// connect the client
client.connect(options);
}
/*连接断开*/
function disconnect(){
client.disconnect();
alert('Connection - Disconnected.');
connected = false;
}
/*发送mqtt消息包
* @topic: 订阅主题 string
* @qos: 消息质量 int
* @message: 消息体
* @retain: 是否保留 bool
*/
function publish(topic, qos, message, retain){
if (!connected) {
alert('mqtt未连接,请稍后再试');
return;
}
alert('Publishing Message: \nTopic: '+topic+'\nQoS: ' + qos + '\nMessage: '+message);
message = new Paho.MQTT.Message(message);
message.destinationName = topic;
message.qos = qos;
message.retained = retain;
client.send(message);
}
/*订阅主题
* @topic: 订阅主题 string
* @qos: 消息质量 int
*/
function subscribe(topic, qos){
if (!connected) {
alert('mqtt未连接,请稍后再试');
return;
}
alert('Subscribing to: \nTopic: ' + topic +'\nQoS: '+qos);
client.subscribe(topic, {qos: qos});
}
/*取消主题订阅
* @topic: 订阅主题 string
* @qos: 消息质量 int
*/
function unsubscribe(topic){
client.unsubscribe(topic, {
onSuccess: unsubscribeSuccess,
onFailure: unsubscribeFailure,
invocationContext: {topic : topic}
});
}
function unsubscribeSuccess(context){
alert('Successfully unsubscribed from ', context.invocationContext.topic);
}
function unsubscribeFailure(context){
alert('Failed to unsubscribe from ', context.invocationContext.topic);
}
// Just in case someone sends html
function safe_tags_regex(str) {
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
}
function makeid()
{
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 5; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}