SlideShare a Scribd company logo
1 of 67
Download to read offline
Give a Push to 
Your Qt 
Application with Qt 
Cloud Services 
and WebSockets
About me
Lauri Nevala 
nevalau nevalla nevalla 
• Working in Qt Cloud Services team at The Qt 
Company 
• Over ten years of experience in creating web and 
mobile based applications
Our Goal 
Understand how to use Qt Cloud Services 
in order to send and receive WebSocket 
messages
What is Qt Cloud Services 
Enginio 
Data 
Storage 
Storage 
for 
Applica/on 
Data 
Use 
with 
QtEnginio 
Library 
Managed 
Applica3on 
Run3me 
Applica/on 
Pla<orm 
as 
a 
Service 
Support 
for 
Qt/C++, 
NodeJS, 
Apache, 
PHP, 
MongoDB, 
MySQL, 
Redis… 
Managed 
WebSocket 
Real-­‐Time 
Socket 
Connec/ons 
with 
virtually 
unlimited 
scalability 
Use 
with 
SDK’s 
and 
Qt 
WebSocket 
Client 
Library
Enginio Data Storage (EDS) 
Flexible and powerful 
cloud data storage 
with built-in user and 
data access control
Managed Application Runtime (MAR) 
Scalable," 
Multi-language," 
Multi-database," 
Application Platform as a Service
Managed Application Runtimes 
How does it work?
Supported Frameworks 
Supported frameworks by 3rd party build packs 
Scala, Clojure, Play, Gradle, Grails, PHP, Go, Meteorite, Perl, Dart, Nginx, Apache, Jekyll
Built-in Services 
or choose from our cloud based services 
Enginio Data Storage" 
Managed WebSocket 
or choose anything with SDK 
... Amazon, Azure, Google ...
Developer Friendly 
Deployment 
Deploy using Git – the most common VCS 
among developers 
> 
git 
push 
qtc 
master
Managed WebSocket (MWS) 
Fully managed 
service implementing 
a bi-directional, real-time 
communication 
gateway for 
WebSockets.
Managed WebSocket 
How does it work?
3. send WebSocket message 
1. get WebSocket URI 
4. deliver WebSocket message 2. open WebSocket 
connection 
{ 
data: 
'{ 
"object":{ 
"id":"541df1c1e5bde554a805b213", 
"createdAt":"2014-­‐09 
20T21:29:37.849Z", 
"device":"FZXC0wg0LvaJ", 
"done":false, 
"objectType":"objects.todos", 
"text":"testi2", 
"updatedAt":"2014-­‐09-­‐20T21:29:37.849Z", 
"userId":"user:54196f3f5a3d8b61860381a4" 
}, 
"meta":{ 
"backendId":"5417e5485a3d8b418a01adb7", 
"eventName":"create", 
"requestId":"a671f67b4f41c20b53988a6057b32539", 
"userId":null} 
}', 
receivers: 
{ 
sockets: 
['*'], 
tags: 
[] 
} 
}
WebSockets 
Consider using WebSockets for instantaneous data 
without the browser refresh
Where to use? 
• Chats 
• Social feeds 
• Multiplayer games 
• Collaborative editing 
• Sport updates 
• Location based apps 
• Your killer app
Why WebSockets are so great? 
• WebSockets defines an API establishing “socket” 
connections between web clients and a server 
• TCP-based protocol 
• Full-duplex, simultaneous bi-directional messaging 
• Uri scheme ws: and wss:
WebSockets and Qt Cloud 
Services 
1. + 
➡ public socket 
2. + + 
➡ private socket 
3. 
➡ do anything you want
Public sockets 
https://flic.kr/p/dUtbk5
+
WebSocket server 
Create EDS instance 
Create MWS instance 
Create EDS Webhook
WebSocket server 
Create EDS instance 
Create MWS instance 
Create EDS Webhook
WebSocket server 
Create EDS instance 
Create MWS instance 
Create EDS Webhook
Create EDS Webhook 
http://bit.ly/eds-mws-webhook
EDS MWS 
{ 
data: 
'{ 
"object":{ 
"id":"541df1c1e5bde554a805b213", 
"createdAt":"2014-­‐09 
20T21:29:37.849Z", 
"device":"FZXC0wg0LvaJ", 
"done":false, 
"objectType":"objects.todos", 
"text":"testi2", 
"updatedAt":"2014-­‐09-­‐20T21:29:37.849Z", 
"userId":"user:54196f3f5a3d8b61860381a4" 
}, 
"meta":{ 
"backendId":"5417e5485a3d8b418a01adb7", 
"eventName":"create", 
"requestId":"a671f67b4f41c20b53988a6057b32539", 
"userId":null} 
}', 
receivers: 
{ 
sockets: 
['*'], 
tags: 
[] 
} 
} 
HTTP POST 
https://mws-eu-1.qtc.io/v1/gateways/MWS_GATEWAY_ID/webhook_receivers/enginio 
App 
{ 
"object":{ 
"id":"541df1c1e5bde554a805b213", 
"createdAt":"2014-­‐09 
20T21:29:37.849Z", 
"device":"FZXC0wg0LvaJ", 
"done":false, 
"objectType":"objects.todos", 
"text":"testi2", 
"updatedAt":"2014-­‐09-­‐20T21:29:37.849Z", 
"userId":"user:54196f3f5a3d8b61860381a4" 
}, 
"meta":{ 
"backendId":"5417e5485a3d8b418a01adb7", 
"eventName":"create", 
"requestId":"a671f67b4f41c20b53988a6057b32539", 
"userId":null} 
} 
} 
send WebSocket message to all sockets
WebSocket server 
Create a EDS instance 
Create a MWS instance 
Create EDS Webhook
Enginio Todo 
http://bit.ly/qtc-todo
2. create Todo 
3. trigger Webhook 
4. send WebSocket message 
5. refresh UI 
1. connect to WebSocket
websocketclient.cpp 
#include 
"websocketclient.h" 
#include 
<QtCore/QDebug> 
" 
QT_USE_NAMESPACE 
" 
WebSocketClient::WebSocketClient(const 
QUrl 
&url, 
QObject 
*parent) 
: 
QObject(parent), 
m_url(url) 
{ 
connect(&m_webSocket, 
&QWebSocket::connected, 
this, 
&WebSocketClient::onConnected); 
connect(&m_webSocket, 
&QWebSocket::disconnected, 
this, 
&WebSocketClient::closed); 
m_webSocket.open(QUrl(url)); 
} 
" 
void 
WebSocketClient::onConnected() 
{ 
qDebug() 
<< 
"WebSocket 
connected"; 
connect(&m_webSocket, 
&QWebSocket::textMessageReceived, 
this, 
&WebSocketClient::onTextMessageReceived); 
} 
" 
void 
WebSocketClient::onTextMessageReceived(QString 
message) 
{ 
emit 
onMessageReceived(message); 
}
mainwindow.cpp 
#define 
REQUEST_URL 
“https://mws-­‐eu-­‐1.qtc.io/v1/gateways/MWS_GATEWAY_ID/websocket_uri” 
" 
MainWindow::MainWindow(QWidget 
*parent) 
: 
QMainWindow(parent) 
{ 
… 
m_networkManager 
= 
new 
QNetworkAccessManager(this); 
QObject::connect(m_networkManager, 
&QNetworkAccessManager::finished, 
this, 
&MainWindow::requestFinished); 
getWebSocketUrl(); 
… 
} 
QNetworkReply* 
MainWindow::getWebSocketUrl() 
{ 
QNetworkRequest 
request; 
request.setUrl(QUrl(QString("%1").arg(REQUEST_URL))); 
request.setHeader(QNetworkRequest::ContentTypeHeader, 
"application/json"); 
" 
QNetworkReply 
*reply 
= 
m_networkManager-­‐>get(request); 
return 
reply; 
} 
void 
MainWindow::requestFinished(QNetworkReply 
*reply) 
{ 
QJsonDocument 
replyData 
= 
QJsonDocument::fromJson(reply-­‐>readAll()); 
QJsonObject 
data 
= 
replyData.object(); 
" 
m_mwsClient 
= 
new 
WebSocketClient(QUrl(data.value("uri").toString()), 
this); 
" 
QObject::connect(m_mwsClient, 
&WebSocketClient::onMessageReceived, 
this, 
&MainWindow::messageReceived); 
}
void 
MainWindow::messageReceived(QString 
message) 
{ 
qDebug() 
<< 
"Message 
received:" 
<< 
message; 
QJsonDocument 
messageJson 
= 
QJsonDocument::fromJson(message.toUtf8()); 
QJsonObject 
enginioObject 
= 
messageJson.object().value("object").toObject(); 
QJsonObject 
metaObject 
= 
messageJson.object().value("meta").toObject(); 
QString 
event 
= 
metaObject.value("eventName").toString(); 
if(event 
== 
"delete" 
|| 
enginioObject.value("device_id").toString() 
!= 
m_device) 
{ 
qDebug() 
<< 
"Refresh 
todos"; 
QJsonObject 
query; 
// 
reload 
todos 
from 
Enginio 
m_model-­‐>setQuery(query); 
" 
query["objectType"] 
= 
QString::fromUtf8("objects.todos"); 
m_model-­‐>setQuery(query); 
" 
} 
}
Demo
Private sockets 
https://flic.kr/p/89crWV
+ +
Server-side app 
// 
Qt 
Cloud 
Services 
package 
var 
qtc 
= 
require('qtc'); 
var 
qtcConfig 
= 
require('../config/qtc-­‐conf'); 
var 
mws 
= 
new 
qtc.Mws(qtcConfig.mws); 
module.exports 
= 
function(app) 
{ 
app.post('/api/websocket/messages', 
function(req, 
res) 
{ 
var 
payload 
= 
req.body.payload; 
console.log('got 
websocket 
request:') 
console.log(payload) 
" 
mws.send(JSON.stringify(payload), 
{ 
sockets: 
null, 
tags: 
[payload.object.userId] 
}, 
function(e, 
mwsResponse) 
{ 
console.log('send 
websocket 
message:'); 
console.log(mwsResponse); 
res.json(mwsResponse); 
}) 
}); 
… 
} 
app.get('/api/websocket', 
function(req, 
res) 
{ 
authenticateRequest(req, 
function(e, 
session){ 
if(!e){ 
mws.createSocket(["user:"+session.userId], 
function(e, 
mwsResponse) 
{ 
res.json(mwsResponse); 
}); 
} 
else 
{ 
res.json(error(403, 
"Access 
Denied!")); 
} 
}); 
});
QML Client 
http://bit.ly/qtc-mar-todo
2. create Todo 
4. trigger Webhook 
5. send WebSocket message 
6. refresh UI 
3. insert Todo 
1. connect to WebSocket
main.qml 
import 
QtQuick 
2.2 
import 
QtQuick.Controls 
1.1 
import 
Qt.WebSockets 
1.0 
import 
"Storage.js" 
as 
Storage 
" 
Item 
{ 
id: 
app 
width: 
480 
height: 
800 
… 
" 
WebSocket 
{ 
id: 
socket 
active: 
true 
onTextMessageReceived: 
{ 
console.log(message) 
Storage.handleWebsocketMessage(message) 
} 
onStatusChanged: 
{ 
if 
(socket.status 
== 
WebSocket.Error) 
{ 
console.log("Error: 
" 
+ 
socket.errorString) 
} 
else 
if 
(socket.status 
== 
WebSocket.Open) 
{ 
console.log("Open") 
} 
else 
if 
(socket.status 
== 
WebSocket.Closed) 
{ 
console.log("Socket 
closed") 
} 
} 
} 
… 
}
storage.js 
var 
REQUEST_URL 
= 
"http://qtc-­‐tutorial-­‐todo.qtcloudapp.com" 
function 
connectToWebSocket() 
{ 
var 
doc 
= 
new 
XMLHttpRequest(); 
doc.open("GET", 
REQUEST_URL 
+ 
"/api/websocket", 
true); 
doc.setRequestHeader('x-­‐todo-­‐session', 
sessionId); 
doc.setRequestHeader('Content-­‐Type', 
'application/json'); 
doc.onreadystatechange 
= 
function() 
{ 
// 
When 
ready 
if 
(doc.readyState 
=== 
4) 
{ 
// 
If 
OK 
if 
(doc.status 
=== 
200) 
{ 
var 
data 
= 
JSON.parse(doc.responseText); 
console.log(doc.responseText) 
socket.url 
= 
data.uri 
} 
} 
} 
doc.send() 
}
function 
handleWebsocketMessage(message) 
{ 
message 
= 
JSON.parse(message) 
var 
event 
= 
message.meta.eventName 
var 
object 
= 
message.object 
if(object.device 
!== 
device) 
{ 
// 
ignore 
events 
created 
by 
this 
app 
var 
i 
if(event 
=== 
"create") 
{ 
addItem(object.text, 
object.id) 
} 
else 
if(event 
=== 
"update") 
{ 
for 
(i=itemModel.count; 
i-­‐-­‐;) 
{ 
if( 
object.id 
=== 
itemModel.get(i).itemId) 
{ 
finishItem(i, 
false) 
break; 
} 
} 
} 
} 
if(event 
=== 
"delete") 
{ 
for 
(i=itemModel.count; 
i-­‐-­‐;) 
{ 
if( 
object.id 
=== 
itemModel.get(i).itemId) 
{ 
deleteItem(i, 
false) 
break; 
} 
} 
} 
}
Demo 
• Try it yourself! 
• http://bit.ly/qtc-todo-demo 
• username: qtincloud 
password: qtincloud
https://flic.kr/p/cT2gqu 
Custom WebSocket Server
em-websocket 
… etc …
I want to use !!!1
Using WebSockets with 
MAR 
• Server must listen to a port that MAR gives to the 
app 
• To keep idle socket connections alive, the 
WebSocket server must send a ping control frame 
to every client at least once in < 60s
Qt WebSocket EchoServer 
http://bit.ly/qt-echoserver 
• Example can be found from Qt 5.3 examples 
• Bug in Qt 5.3 that prevents deploying it to MAR 
• Fixed in Qt 5.4 
• Qt 5.4 beta in MAR allows us to test it out
main.cpp 
#include 
<QtCore/QCoreApplication> 
#include 
"echoserver.h" 
" 
int 
main(int 
argc, 
char 
*argv[]) 
{ 
QCoreApplication 
a(argc, 
argv); 
int 
port 
= 
1234; 
if(qEnvironmentVariableIsSet("PORT") 
&& 
!qEnvironmentVariableIsEmpty("PORT")) 
{ 
port 
= 
qgetenv("PORT").toInt(); 
} 
EchoServer 
*server 
= 
new 
EchoServer(port); 
QObject::connect(server, 
&EchoServer::closed, 
&a, 
&QCoreApplication::quit); 
" 
return 
a.exec(); 
}
echoserver.cpp 
EchoServer::EchoServer(quint16 
port, 
QObject 
*parent) 
: 
QObject(parent), 
m_pWebSocketServer(new 
QWebSocketServer(QStringLiteral("Echo 
Server"), 
QWebSocketServer::NonSecureMode, 
this)), 
m_clients() 
{ 
if 
(m_pWebSocketServer-­‐>listen(QHostAddress::Any, 
port)) 
{ 
… 
QTimer 
*timer 
= 
new 
QTimer(this); 
connect(timer, 
&QTimer::timeout, 
this, 
&EchoServer::pingClients); 
timer-­‐>start(50000); 
} 
} 
void 
EchoServer::pingClients() 
{ 
if(m_clients.length() 
> 
0) 
{ 
qDebug() 
<< 
"Ping 
clients 
" 
<< 
m_clients.length(); 
for(int 
i 
= 
0; 
i< 
m_clients.length(); 
i++) 
{ 
m_clients[i]-­‐>ping(); 
} 
} 
" 
}
Demo
How to Use With Qt? 
lanevala@it-l-m0015 ~/Development/qtwebsockets-echoserver-example[master*]$ git push qtc master 
Counting objects: 1, done. 
Writing objects: 100% (1/1), 186 bytes | 0 bytes/s, done. 
Total 1 (delta 0), reused 0 (delta 0) 
-----> Qt app detected 
Installing Qt 5.4.0-beta-2014-09-25_25 
-----> Setting up Qt 5.4.0-beta-2014-09-25_25 
-----> Configuring with qmake 
-----> Compiling with make 
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -fPIE -DQT_NO_DEBUG -DQT_WEBSOCKETS_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB - 
I.qtcs/Qt/5.4/gcc_64/mkspecs/linux-g++ -I. -I.qtcs/Qt/5.4/gcc_64/include -I.qtcs/Qt/5.4/gcc_64/include/QtWebSockets - 
I.qtcs/Qt/5.4/gcc_64/include/QtNetwork -I.qtcs/Qt/5.4/gcc_64/include/QtCore -I. -o main.o main.cpp 
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -fPIE -DQT_NO_DEBUG -DQT_WEBSOCKETS_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB - 
I.qtcs/Qt/5.4/gcc_64/mkspecs/linux-g++ -I. -I.qtcs/Qt/5.4/gcc_64/include -I.qtcs/Qt/5.4/gcc_64/include/QtWebSockets - 
I.qtcs/Qt/5.4/gcc_64/include/QtNetwork -I.qtcs/Qt/5.4/gcc_64/include/QtCore -I. -o echoserver.o echoserver.cpp 
/app/.qtcs/Qt/5.4/gcc_64/bin/moc -DQT_NO_DEBUG -DQT_WEBSOCKETS_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I/app/.qtcs/Qt/ 
5.4/gcc_64/mkspecs/linux-g++ -I/tmp/build -I/app/.qtcs/Qt/5.4/gcc_64/include -I/app/.qtcs/Qt/5.4/gcc_64/include/ 
QtWebSockets -I/app/.qtcs/Qt/5.4/gcc_64/include/QtNetwork -I/app/.qtcs/Qt/5.4/gcc_64/include/QtCore echoserver.h -o 
moc_echoserver.cpp 
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -fPIE -DQT_NO_DEBUG -DQT_WEBSOCKETS_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB - 
I.qtcs/Qt/5.4/gcc_64/mkspecs/linux-g++ -I. -I.qtcs/Qt/5.4/gcc_64/include -I.qtcs/Qt/5.4/gcc_64/include/QtWebSockets - 
I.qtcs/Qt/5.4/gcc_64/include/QtNetwork -I.qtcs/Qt/5.4/gcc_64/include/QtCore -I. -o moc_echoserver.o moc_echoserver.cpp 
g++ -Wl,-O1 -Wl,-rpath,/app/.qtcs/Qt/5.4/gcc_64 -Wl,-rpath,/app/.qtcs/Qt/5.4/gcc_64/lib -o echoserver main.o 
echoserver.o moc_echoserver.o -L/app/.qtcs/Qt/5.4/gcc_64/lib -lQt5WebSockets -lQt5Network -lQt5Core -lpthread 
-----> Discovering process types 
Procfile declares types -> web 
-----> Compiled slug size is 108M 
-----> Deploying app 
Uploading app container ...... done. 
mar-eu-1-twwto7g0 deployed to http://mar-eu-1-twwto8g1.qtcloudapp.com
CONNECTED 
Does it echo? 
Does it echo? 
Echoserver listening on port 5000 
Echoserver got new connection 
Ping clients 1 
Echoserver got new pong 
Echoserver got new message "Does it echo?"
Qt WebChannel 
• The Qt WebChannel module provides a library for 
seamless integration of C++ and QML applications 
with HTML/JavaScript clients. 
• Any QObject can be published to remote clients, 
where its public API becomes available.
Example 
http://bit.ly/qtc-webchannel 
• Qt WebChannel Standalone example from Qt 5.4 
examples 
• Instead of local WebSocket server, we are using 
WebSocket server running on MAR
WebSocketClientWrapper.cpp 
/*! 
Construct 
the 
client 
wrapper 
with 
the 
given 
url. 
" 
All 
clients 
connecting 
to 
the 
QWebSocketServer 
will 
be 
automatically 
wrapped 
in 
WebSocketTransport 
objects. 
*/ 
WebSocketClientWrapper::WebSocketClientWrapper(const 
QUrl 
&url, 
QObject 
*parent) 
: 
QObject(parent) 
, 
m_url(url) 
{ 
qWarning() 
<< 
"Open 
WebSocket 
connection: 
" 
<< 
m_url; 
connect(&m_webSocket, 
&QWebSocket::connected, 
this, 
&WebSocketClientWrapper::handleNewConnection); 
m_webSocket.open(url); 
} 
" 
/*! 
Wrap 
an 
incoming 
WebSocket 
connection 
in 
a 
WebSocketTransport 
object. 
*/ 
void 
WebSocketClientWrapper::handleNewConnection() 
{ 
qWarning() 
<< 
"WebSocket 
connected: 
" 
<< 
m_url; 
emit 
clientConnected(new 
WebSocketTransport(&m_webSocket)); 
}
main.cpp 
// 
wrap 
WebSocket 
clients 
in 
QWebChannelAbstractTransport 
objects 
WebSocketClientWrapper 
clientWrapper(QUrl("wss://mar-­‐eu-­‐1-­‐twwto7g0.qtcloudapp.com")); 
" 
// 
setup 
the 
channel 
QWebChannel 
channel; 
QObject::connect(&clientWrapper, 
&WebSocketClientWrapper::clientConnected, 
&channel, 
&QWebChannel::connectTo); 
" 
// 
setup 
the 
dialog 
and 
publish 
it 
to 
the 
QWebChannel 
Dialog 
dialog; 
channel.registerObject(QStringLiteral("dialog"), 
&dialog);
index.html 
window.onload 
= 
function() 
{ 
var 
baseUrl 
= 
"wss://mar-­‐eu-­‐1-­‐twwto7g0.qtcloudapp.com"; 
output("Connecting 
to 
WebSocket 
server 
at 
" 
+ 
baseUrl 
+ 
"."); 
var 
socket 
= 
new 
WebSocket(baseUrl); 
socket.onopen 
= 
function() 
{ 
output("WebSocket 
connected, 
setting 
up 
QWebChannel."); 
new 
QWebChannel(socket, 
function(channel) 
{ 
// 
make 
dialog 
object 
accessible 
globally 
window.dialog 
= 
channel.objects.dialog; 
" 
document.getElementById("send").onclick 
= 
function() 
{ 
var 
input 
= 
document.getElementById("input"); 
var 
text 
= 
input.value; 
if 
(!text) 
{ 
return; 
} 
" 
output("Sent 
message: 
" 
+ 
text); 
input.value 
= 
""; 
dialog.receiveText(text); 
} 
" 
dialog.sendText.connect(function(message) 
{ 
output("Received 
message: 
" 
+ 
message); 
}); 
" 
dialog.receiveText("Client 
connected, 
ready 
to 
send/receive 
messages!"); 
output("Connected 
to 
WebChannel, 
ready 
to 
send/receive 
messages!"); 
}); 
} 
}
Demo
QML HTML 
Initializing WebChannel... 
Initialization complete, opening browser at file:/// 
Users/lanevala/Qt5.4.0/Examples/Qt-5.4/ 
webchannel/build-standalone- 
Desktop_Qt_5_4_clang_64bit-Debug/index.html. 
Received message: Client connected, ready to 
send/receive messages! 
Text Message 
Connecting to WebSocket server at wss://mar-eu-1- 
twwto7g0.qtcloudapp.com. 
WebSocket connected, setting up QWebChannel. 
Connected to WebChannel, ready to send/receive messages! 
Sent message: Test message 
Received message: Test message
Summary 
• WebSockets are great 
• Using WebSockets with Qt and Qt Cloud Services is 
super easy and fast 
• There are multiple levels on you can utilise Qt Cloud 
Services to send and receive WebSocket messages 
• Use Managed WebSocket service 
• Deploy your own solution to MAR
Further actions 
• Visit qtcloudservices.com 
• Sign-up 
• Use it 
• Give us feedback 
• Qt forum 
• info@qtcloudservices.com
Thank you! 
Source Codes: 
• Enginio Todo: 
http://bit.ly/qtc-todo 
• Qt Cloud Services Todo: 
http://bit.ly/qtc-mar-todo 
• Qt WebSocket Echo Server: 
http://bit.ly/qt-echoserver

More Related Content

Viewers also liked

CV Roy Basoeki
CV Roy BasoekiCV Roy Basoeki
CV Roy Basoeki
time4web
 
Aplikom_Unsri_1. MyBiodata dan keunikan Matematika_Sutri Octaviana
Aplikom_Unsri_1. MyBiodata dan keunikan Matematika_Sutri OctavianaAplikom_Unsri_1. MyBiodata dan keunikan Matematika_Sutri Octaviana
Aplikom_Unsri_1. MyBiodata dan keunikan Matematika_Sutri Octaviana
sutrioctavianasitorus
 
Microorganisms
MicroorganismsMicroorganisms
Microorganisms
sunilbhil
 
Book4 unit1-lesson5
Book4 unit1-lesson5Book4 unit1-lesson5
Book4 unit1-lesson5
stthomas8
 
Aspire one series service guide
Aspire one series service guideAspire one series service guide
Aspire one series service guide
Setyo Prasadja
 

Viewers also liked (17)

Everybody Polyglot! - Cross-Language RPC with Erlang
Everybody Polyglot! - Cross-Language RPC with ErlangEverybody Polyglot! - Cross-Language RPC with Erlang
Everybody Polyglot! - Cross-Language RPC with Erlang
 
Yg Ini 1
Yg Ini 1Yg Ini 1
Yg Ini 1
 
Sulucionario electromagnetismo cheng
Sulucionario electromagnetismo cheng Sulucionario electromagnetismo cheng
Sulucionario electromagnetismo cheng
 
33 Period week
33 Period week33 Period week
33 Period week
 
Tarif jne-reg-2013-bdg-1-juni-2013
Tarif jne-reg-2013-bdg-1-juni-2013Tarif jne-reg-2013-bdg-1-juni-2013
Tarif jne-reg-2013-bdg-1-juni-2013
 
Hwswb
HwswbHwswb
Hwswb
 
CV Roy Basoeki
CV Roy BasoekiCV Roy Basoeki
CV Roy Basoeki
 
Say little, do more.
Say little, do more.Say little, do more.
Say little, do more.
 
Poor Pigs
Poor PigsPoor Pigs
Poor Pigs
 
англійська мова 3 кл підручник
англійська мова 3 кл підручниканглійська мова 3 кл підручник
англійська мова 3 кл підручник
 
Aplikom_Unsri_1. MyBiodata dan keunikan Matematika_Sutri Octaviana
Aplikom_Unsri_1. MyBiodata dan keunikan Matematika_Sutri OctavianaAplikom_Unsri_1. MyBiodata dan keunikan Matematika_Sutri Octaviana
Aplikom_Unsri_1. MyBiodata dan keunikan Matematika_Sutri Octaviana
 
Microorganisms
MicroorganismsMicroorganisms
Microorganisms
 
Global and china obd telematics industry report, 2014 2015
Global and china obd telematics industry report, 2014 2015Global and china obd telematics industry report, 2014 2015
Global and china obd telematics industry report, 2014 2015
 
Book4 unit1-lesson5
Book4 unit1-lesson5Book4 unit1-lesson5
Book4 unit1-lesson5
 
Monografia fic
Monografia ficMonografia fic
Monografia fic
 
Aspire one series service guide
Aspire one series service guideAspire one series service guide
Aspire one series service guide
 
Inside sina weibo
Inside sina weiboInside sina weibo
Inside sina weibo
 

Recently uploaded

一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
ayvbos
 
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdfpdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
JOHNBEBONYAP1
 
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girlsRussian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
Monica Sydney
 
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
ydyuyu
 
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi EscortsRussian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Monica Sydney
 
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
gajnagarg
 
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu DhabiAbu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Monica Sydney
 
一比一原版奥兹学院毕业证如何办理
一比一原版奥兹学院毕业证如何办理一比一原版奥兹学院毕业证如何办理
一比一原版奥兹学院毕业证如何办理
F
 

Recently uploaded (20)

APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...
APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...
APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...
 
"Boost Your Digital Presence: Partner with a Leading SEO Agency"
"Boost Your Digital Presence: Partner with a Leading SEO Agency""Boost Your Digital Presence: Partner with a Leading SEO Agency"
"Boost Your Digital Presence: Partner with a Leading SEO Agency"
 
Trump Diapers Over Dems t shirts Sweatshirt
Trump Diapers Over Dems t shirts SweatshirtTrump Diapers Over Dems t shirts Sweatshirt
Trump Diapers Over Dems t shirts Sweatshirt
 
Story Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
Story Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrStory Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
Story Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
 
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
一比一原版(Flinders毕业证书)弗林德斯大学毕业证原件一模一样
 
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
20240510 QFM016 Irresponsible AI Reading List April 2024.pdf
 
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdfpdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
 
Tadepalligudem Escorts Service Girl ^ 9332606886, WhatsApp Anytime Tadepallig...
Tadepalligudem Escorts Service Girl ^ 9332606886, WhatsApp Anytime Tadepallig...Tadepalligudem Escorts Service Girl ^ 9332606886, WhatsApp Anytime Tadepallig...
Tadepalligudem Escorts Service Girl ^ 9332606886, WhatsApp Anytime Tadepallig...
 
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girlsRussian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
Russian Call girls in Abu Dhabi 0508644382 Abu Dhabi Call girls
 
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
 
Real Men Wear Diapers T Shirts sweatshirt
Real Men Wear Diapers T Shirts sweatshirtReal Men Wear Diapers T Shirts sweatshirt
Real Men Wear Diapers T Shirts sweatshirt
 
20240508 QFM014 Elixir Reading List April 2024.pdf
20240508 QFM014 Elixir Reading List April 2024.pdf20240508 QFM014 Elixir Reading List April 2024.pdf
20240508 QFM014 Elixir Reading List April 2024.pdf
 
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime NagercoilNagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
 
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi EscortsRussian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
Russian Escort Abu Dhabi 0503464457 Abu DHabi Escorts
 
Local Call Girls in Seoni 9332606886 HOT & SEXY Models beautiful and charmin...
Local Call Girls in Seoni  9332606886 HOT & SEXY Models beautiful and charmin...Local Call Girls in Seoni  9332606886 HOT & SEXY Models beautiful and charmin...
Local Call Girls in Seoni 9332606886 HOT & SEXY Models beautiful and charmin...
 
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
 
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
Top profile Call Girls In Dindigul [ 7014168258 ] Call Me For Genuine Models ...
 
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu DhabiAbu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
Abu Dhabi Escorts Service 0508644382 Escorts in Abu Dhabi
 
一比一原版奥兹学院毕业证如何办理
一比一原版奥兹学院毕业证如何办理一比一原版奥兹学院毕业证如何办理
一比一原版奥兹学院毕业证如何办理
 
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
 

Give a Push to Your Qt Application with Websockets

  • 1. Give a Push to Your Qt Application with Qt Cloud Services and WebSockets
  • 3. Lauri Nevala nevalau nevalla nevalla • Working in Qt Cloud Services team at The Qt Company • Over ten years of experience in creating web and mobile based applications
  • 4. Our Goal Understand how to use Qt Cloud Services in order to send and receive WebSocket messages
  • 5.
  • 6. What is Qt Cloud Services Enginio Data Storage Storage for Applica/on Data Use with QtEnginio Library Managed Applica3on Run3me Applica/on Pla<orm as a Service Support for Qt/C++, NodeJS, Apache, PHP, MongoDB, MySQL, Redis… Managed WebSocket Real-­‐Time Socket Connec/ons with virtually unlimited scalability Use with SDK’s and Qt WebSocket Client Library
  • 7. Enginio Data Storage (EDS) Flexible and powerful cloud data storage with built-in user and data access control
  • 8. Managed Application Runtime (MAR) Scalable," Multi-language," Multi-database," Application Platform as a Service
  • 9. Managed Application Runtimes How does it work?
  • 10. Supported Frameworks Supported frameworks by 3rd party build packs Scala, Clojure, Play, Gradle, Grails, PHP, Go, Meteorite, Perl, Dart, Nginx, Apache, Jekyll
  • 11. Built-in Services or choose from our cloud based services Enginio Data Storage" Managed WebSocket or choose anything with SDK ... Amazon, Azure, Google ...
  • 12. Developer Friendly Deployment Deploy using Git – the most common VCS among developers > git push qtc master
  • 13. Managed WebSocket (MWS) Fully managed service implementing a bi-directional, real-time communication gateway for WebSockets.
  • 14. Managed WebSocket How does it work?
  • 15. 3. send WebSocket message 1. get WebSocket URI 4. deliver WebSocket message 2. open WebSocket connection { data: '{ "object":{ "id":"541df1c1e5bde554a805b213", "createdAt":"2014-­‐09 20T21:29:37.849Z", "device":"FZXC0wg0LvaJ", "done":false, "objectType":"objects.todos", "text":"testi2", "updatedAt":"2014-­‐09-­‐20T21:29:37.849Z", "userId":"user:54196f3f5a3d8b61860381a4" }, "meta":{ "backendId":"5417e5485a3d8b418a01adb7", "eventName":"create", "requestId":"a671f67b4f41c20b53988a6057b32539", "userId":null} }', receivers: { sockets: ['*'], tags: [] } }
  • 16. WebSockets Consider using WebSockets for instantaneous data without the browser refresh
  • 17. Where to use? • Chats • Social feeds • Multiplayer games • Collaborative editing • Sport updates • Location based apps • Your killer app
  • 18. Why WebSockets are so great? • WebSockets defines an API establishing “socket” connections between web clients and a server • TCP-based protocol • Full-duplex, simultaneous bi-directional messaging • Uri scheme ws: and wss:
  • 19. WebSockets and Qt Cloud Services 1. + ➡ public socket 2. + + ➡ private socket 3. ➡ do anything you want
  • 21. +
  • 22. WebSocket server Create EDS instance Create MWS instance Create EDS Webhook
  • 23.
  • 24. WebSocket server Create EDS instance Create MWS instance Create EDS Webhook
  • 25.
  • 26.
  • 27. WebSocket server Create EDS instance Create MWS instance Create EDS Webhook
  • 28. Create EDS Webhook http://bit.ly/eds-mws-webhook
  • 29. EDS MWS { data: '{ "object":{ "id":"541df1c1e5bde554a805b213", "createdAt":"2014-­‐09 20T21:29:37.849Z", "device":"FZXC0wg0LvaJ", "done":false, "objectType":"objects.todos", "text":"testi2", "updatedAt":"2014-­‐09-­‐20T21:29:37.849Z", "userId":"user:54196f3f5a3d8b61860381a4" }, "meta":{ "backendId":"5417e5485a3d8b418a01adb7", "eventName":"create", "requestId":"a671f67b4f41c20b53988a6057b32539", "userId":null} }', receivers: { sockets: ['*'], tags: [] } } HTTP POST https://mws-eu-1.qtc.io/v1/gateways/MWS_GATEWAY_ID/webhook_receivers/enginio App { "object":{ "id":"541df1c1e5bde554a805b213", "createdAt":"2014-­‐09 20T21:29:37.849Z", "device":"FZXC0wg0LvaJ", "done":false, "objectType":"objects.todos", "text":"testi2", "updatedAt":"2014-­‐09-­‐20T21:29:37.849Z", "userId":"user:54196f3f5a3d8b61860381a4" }, "meta":{ "backendId":"5417e5485a3d8b418a01adb7", "eventName":"create", "requestId":"a671f67b4f41c20b53988a6057b32539", "userId":null} } } send WebSocket message to all sockets
  • 30. WebSocket server Create a EDS instance Create a MWS instance Create EDS Webhook
  • 32. 2. create Todo 3. trigger Webhook 4. send WebSocket message 5. refresh UI 1. connect to WebSocket
  • 33. websocketclient.cpp #include "websocketclient.h" #include <QtCore/QDebug> " QT_USE_NAMESPACE " WebSocketClient::WebSocketClient(const QUrl &url, QObject *parent) : QObject(parent), m_url(url) { connect(&m_webSocket, &QWebSocket::connected, this, &WebSocketClient::onConnected); connect(&m_webSocket, &QWebSocket::disconnected, this, &WebSocketClient::closed); m_webSocket.open(QUrl(url)); } " void WebSocketClient::onConnected() { qDebug() << "WebSocket connected"; connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &WebSocketClient::onTextMessageReceived); } " void WebSocketClient::onTextMessageReceived(QString message) { emit onMessageReceived(message); }
  • 34. mainwindow.cpp #define REQUEST_URL “https://mws-­‐eu-­‐1.qtc.io/v1/gateways/MWS_GATEWAY_ID/websocket_uri” " MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { … m_networkManager = new QNetworkAccessManager(this); QObject::connect(m_networkManager, &QNetworkAccessManager::finished, this, &MainWindow::requestFinished); getWebSocketUrl(); … } QNetworkReply* MainWindow::getWebSocketUrl() { QNetworkRequest request; request.setUrl(QUrl(QString("%1").arg(REQUEST_URL))); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); " QNetworkReply *reply = m_networkManager-­‐>get(request); return reply; } void MainWindow::requestFinished(QNetworkReply *reply) { QJsonDocument replyData = QJsonDocument::fromJson(reply-­‐>readAll()); QJsonObject data = replyData.object(); " m_mwsClient = new WebSocketClient(QUrl(data.value("uri").toString()), this); " QObject::connect(m_mwsClient, &WebSocketClient::onMessageReceived, this, &MainWindow::messageReceived); }
  • 35. void MainWindow::messageReceived(QString message) { qDebug() << "Message received:" << message; QJsonDocument messageJson = QJsonDocument::fromJson(message.toUtf8()); QJsonObject enginioObject = messageJson.object().value("object").toObject(); QJsonObject metaObject = messageJson.object().value("meta").toObject(); QString event = metaObject.value("eventName").toString(); if(event == "delete" || enginioObject.value("device_id").toString() != m_device) { qDebug() << "Refresh todos"; QJsonObject query; // reload todos from Enginio m_model-­‐>setQuery(query); " query["objectType"] = QString::fromUtf8("objects.todos"); m_model-­‐>setQuery(query); " } }
  • 36. Demo
  • 37.
  • 39. + +
  • 40. Server-side app // Qt Cloud Services package var qtc = require('qtc'); var qtcConfig = require('../config/qtc-­‐conf'); var mws = new qtc.Mws(qtcConfig.mws); module.exports = function(app) { app.post('/api/websocket/messages', function(req, res) { var payload = req.body.payload; console.log('got websocket request:') console.log(payload) " mws.send(JSON.stringify(payload), { sockets: null, tags: [payload.object.userId] }, function(e, mwsResponse) { console.log('send websocket message:'); console.log(mwsResponse); res.json(mwsResponse); }) }); … } app.get('/api/websocket', function(req, res) { authenticateRequest(req, function(e, session){ if(!e){ mws.createSocket(["user:"+session.userId], function(e, mwsResponse) { res.json(mwsResponse); }); } else { res.json(error(403, "Access Denied!")); } }); });
  • 42. 2. create Todo 4. trigger Webhook 5. send WebSocket message 6. refresh UI 3. insert Todo 1. connect to WebSocket
  • 43. main.qml import QtQuick 2.2 import QtQuick.Controls 1.1 import Qt.WebSockets 1.0 import "Storage.js" as Storage " Item { id: app width: 480 height: 800 … " WebSocket { id: socket active: true onTextMessageReceived: { console.log(message) Storage.handleWebsocketMessage(message) } onStatusChanged: { if (socket.status == WebSocket.Error) { console.log("Error: " + socket.errorString) } else if (socket.status == WebSocket.Open) { console.log("Open") } else if (socket.status == WebSocket.Closed) { console.log("Socket closed") } } } … }
  • 44. storage.js var REQUEST_URL = "http://qtc-­‐tutorial-­‐todo.qtcloudapp.com" function connectToWebSocket() { var doc = new XMLHttpRequest(); doc.open("GET", REQUEST_URL + "/api/websocket", true); doc.setRequestHeader('x-­‐todo-­‐session', sessionId); doc.setRequestHeader('Content-­‐Type', 'application/json'); doc.onreadystatechange = function() { // When ready if (doc.readyState === 4) { // If OK if (doc.status === 200) { var data = JSON.parse(doc.responseText); console.log(doc.responseText) socket.url = data.uri } } } doc.send() }
  • 45. function handleWebsocketMessage(message) { message = JSON.parse(message) var event = message.meta.eventName var object = message.object if(object.device !== device) { // ignore events created by this app var i if(event === "create") { addItem(object.text, object.id) } else if(event === "update") { for (i=itemModel.count; i-­‐-­‐;) { if( object.id === itemModel.get(i).itemId) { finishItem(i, false) break; } } } } if(event === "delete") { for (i=itemModel.count; i-­‐-­‐;) { if( object.id === itemModel.get(i).itemId) { deleteItem(i, false) break; } } } }
  • 46. Demo • Try it yourself! • http://bit.ly/qtc-todo-demo • username: qtincloud password: qtincloud
  • 48.
  • 50. I want to use !!!1
  • 51. Using WebSockets with MAR • Server must listen to a port that MAR gives to the app • To keep idle socket connections alive, the WebSocket server must send a ping control frame to every client at least once in < 60s
  • 52. Qt WebSocket EchoServer http://bit.ly/qt-echoserver • Example can be found from Qt 5.3 examples • Bug in Qt 5.3 that prevents deploying it to MAR • Fixed in Qt 5.4 • Qt 5.4 beta in MAR allows us to test it out
  • 53. main.cpp #include <QtCore/QCoreApplication> #include "echoserver.h" " int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); int port = 1234; if(qEnvironmentVariableIsSet("PORT") && !qEnvironmentVariableIsEmpty("PORT")) { port = qgetenv("PORT").toInt(); } EchoServer *server = new EchoServer(port); QObject::connect(server, &EchoServer::closed, &a, &QCoreApplication::quit); " return a.exec(); }
  • 54. echoserver.cpp EchoServer::EchoServer(quint16 port, QObject *parent) : QObject(parent), m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Echo Server"), QWebSocketServer::NonSecureMode, this)), m_clients() { if (m_pWebSocketServer-­‐>listen(QHostAddress::Any, port)) { … QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &EchoServer::pingClients); timer-­‐>start(50000); } } void EchoServer::pingClients() { if(m_clients.length() > 0) { qDebug() << "Ping clients " << m_clients.length(); for(int i = 0; i< m_clients.length(); i++) { m_clients[i]-­‐>ping(); } } " }
  • 55. Demo
  • 56. How to Use With Qt? lanevala@it-l-m0015 ~/Development/qtwebsockets-echoserver-example[master*]$ git push qtc master Counting objects: 1, done. Writing objects: 100% (1/1), 186 bytes | 0 bytes/s, done. Total 1 (delta 0), reused 0 (delta 0) -----> Qt app detected Installing Qt 5.4.0-beta-2014-09-25_25 -----> Setting up Qt 5.4.0-beta-2014-09-25_25 -----> Configuring with qmake -----> Compiling with make g++ -c -pipe -O2 -Wall -W -D_REENTRANT -fPIE -DQT_NO_DEBUG -DQT_WEBSOCKETS_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB - I.qtcs/Qt/5.4/gcc_64/mkspecs/linux-g++ -I. -I.qtcs/Qt/5.4/gcc_64/include -I.qtcs/Qt/5.4/gcc_64/include/QtWebSockets - I.qtcs/Qt/5.4/gcc_64/include/QtNetwork -I.qtcs/Qt/5.4/gcc_64/include/QtCore -I. -o main.o main.cpp g++ -c -pipe -O2 -Wall -W -D_REENTRANT -fPIE -DQT_NO_DEBUG -DQT_WEBSOCKETS_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB - I.qtcs/Qt/5.4/gcc_64/mkspecs/linux-g++ -I. -I.qtcs/Qt/5.4/gcc_64/include -I.qtcs/Qt/5.4/gcc_64/include/QtWebSockets - I.qtcs/Qt/5.4/gcc_64/include/QtNetwork -I.qtcs/Qt/5.4/gcc_64/include/QtCore -I. -o echoserver.o echoserver.cpp /app/.qtcs/Qt/5.4/gcc_64/bin/moc -DQT_NO_DEBUG -DQT_WEBSOCKETS_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I/app/.qtcs/Qt/ 5.4/gcc_64/mkspecs/linux-g++ -I/tmp/build -I/app/.qtcs/Qt/5.4/gcc_64/include -I/app/.qtcs/Qt/5.4/gcc_64/include/ QtWebSockets -I/app/.qtcs/Qt/5.4/gcc_64/include/QtNetwork -I/app/.qtcs/Qt/5.4/gcc_64/include/QtCore echoserver.h -o moc_echoserver.cpp g++ -c -pipe -O2 -Wall -W -D_REENTRANT -fPIE -DQT_NO_DEBUG -DQT_WEBSOCKETS_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB - I.qtcs/Qt/5.4/gcc_64/mkspecs/linux-g++ -I. -I.qtcs/Qt/5.4/gcc_64/include -I.qtcs/Qt/5.4/gcc_64/include/QtWebSockets - I.qtcs/Qt/5.4/gcc_64/include/QtNetwork -I.qtcs/Qt/5.4/gcc_64/include/QtCore -I. -o moc_echoserver.o moc_echoserver.cpp g++ -Wl,-O1 -Wl,-rpath,/app/.qtcs/Qt/5.4/gcc_64 -Wl,-rpath,/app/.qtcs/Qt/5.4/gcc_64/lib -o echoserver main.o echoserver.o moc_echoserver.o -L/app/.qtcs/Qt/5.4/gcc_64/lib -lQt5WebSockets -lQt5Network -lQt5Core -lpthread -----> Discovering process types Procfile declares types -> web -----> Compiled slug size is 108M -----> Deploying app Uploading app container ...... done. mar-eu-1-twwto7g0 deployed to http://mar-eu-1-twwto8g1.qtcloudapp.com
  • 57. CONNECTED Does it echo? Does it echo? Echoserver listening on port 5000 Echoserver got new connection Ping clients 1 Echoserver got new pong Echoserver got new message "Does it echo?"
  • 58. Qt WebChannel • The Qt WebChannel module provides a library for seamless integration of C++ and QML applications with HTML/JavaScript clients. • Any QObject can be published to remote clients, where its public API becomes available.
  • 59. Example http://bit.ly/qtc-webchannel • Qt WebChannel Standalone example from Qt 5.4 examples • Instead of local WebSocket server, we are using WebSocket server running on MAR
  • 60. WebSocketClientWrapper.cpp /*! Construct the client wrapper with the given url. " All clients connecting to the QWebSocketServer will be automatically wrapped in WebSocketTransport objects. */ WebSocketClientWrapper::WebSocketClientWrapper(const QUrl &url, QObject *parent) : QObject(parent) , m_url(url) { qWarning() << "Open WebSocket connection: " << m_url; connect(&m_webSocket, &QWebSocket::connected, this, &WebSocketClientWrapper::handleNewConnection); m_webSocket.open(url); } " /*! Wrap an incoming WebSocket connection in a WebSocketTransport object. */ void WebSocketClientWrapper::handleNewConnection() { qWarning() << "WebSocket connected: " << m_url; emit clientConnected(new WebSocketTransport(&m_webSocket)); }
  • 61. main.cpp // wrap WebSocket clients in QWebChannelAbstractTransport objects WebSocketClientWrapper clientWrapper(QUrl("wss://mar-­‐eu-­‐1-­‐twwto7g0.qtcloudapp.com")); " // setup the channel QWebChannel channel; QObject::connect(&clientWrapper, &WebSocketClientWrapper::clientConnected, &channel, &QWebChannel::connectTo); " // setup the dialog and publish it to the QWebChannel Dialog dialog; channel.registerObject(QStringLiteral("dialog"), &dialog);
  • 62. index.html window.onload = function() { var baseUrl = "wss://mar-­‐eu-­‐1-­‐twwto7g0.qtcloudapp.com"; output("Connecting to WebSocket server at " + baseUrl + "."); var socket = new WebSocket(baseUrl); socket.onopen = function() { output("WebSocket connected, setting up QWebChannel."); new QWebChannel(socket, function(channel) { // make dialog object accessible globally window.dialog = channel.objects.dialog; " document.getElementById("send").onclick = function() { var input = document.getElementById("input"); var text = input.value; if (!text) { return; } " output("Sent message: " + text); input.value = ""; dialog.receiveText(text); } " dialog.sendText.connect(function(message) { output("Received message: " + message); }); " dialog.receiveText("Client connected, ready to send/receive messages!"); output("Connected to WebChannel, ready to send/receive messages!"); }); } }
  • 63. Demo
  • 64. QML HTML Initializing WebChannel... Initialization complete, opening browser at file:/// Users/lanevala/Qt5.4.0/Examples/Qt-5.4/ webchannel/build-standalone- Desktop_Qt_5_4_clang_64bit-Debug/index.html. Received message: Client connected, ready to send/receive messages! Text Message Connecting to WebSocket server at wss://mar-eu-1- twwto7g0.qtcloudapp.com. WebSocket connected, setting up QWebChannel. Connected to WebChannel, ready to send/receive messages! Sent message: Test message Received message: Test message
  • 65. Summary • WebSockets are great • Using WebSockets with Qt and Qt Cloud Services is super easy and fast • There are multiple levels on you can utilise Qt Cloud Services to send and receive WebSocket messages • Use Managed WebSocket service • Deploy your own solution to MAR
  • 66. Further actions • Visit qtcloudservices.com • Sign-up • Use it • Give us feedback • Qt forum • info@qtcloudservices.com
  • 67. Thank you! Source Codes: • Enginio Todo: http://bit.ly/qtc-todo • Qt Cloud Services Todo: http://bit.ly/qtc-mar-todo • Qt WebSocket Echo Server: http://bit.ly/qt-echoserver