2020-04-01 03:37:22 +02:00
<!doctype html>
< html lang = "en" class = "no-js" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width,initial-scale=1" >
< meta http-equiv = "x-ua-compatible" content = "ie=edge" >
< meta name = "lang:clipboard.copy" content = "Copy to clipboard" >
< meta name = "lang:clipboard.copied" content = "Copied to clipboard" >
< meta name = "lang:search.language" content = "en" >
< meta name = "lang:search.pipeline.stopwords" content = "True" >
< meta name = "lang:search.pipeline.trimmer" content = "True" >
< meta name = "lang:search.result.none" content = "No matching documents" >
< meta name = "lang:search.result.one" content = "1 matching document" >
< meta name = "lang:search.result.other" content = "# matching documents" >
< meta name = "lang:search.tokenizer" content = "[\s\-]+" >
< link rel = "shortcut icon" href = "../assets/images/favicon.png" >
< meta name = "generator" content = "mkdocs-1.1, mkdocs-material-4.6.3" >
< title > Examples - IXWebSocket< / title >
< link rel = "stylesheet" href = "../assets/stylesheets/application.adb8469c.css" >
< script src = "../assets/javascripts/modernizr.86422ebf.js" > < / script >
< link href = "https://fonts.gstatic.com" rel = "preconnect" crossorigin >
< link rel = "stylesheet" href = "https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&display=fallback" >
< style > body , input { font-family : "Roboto" , "Helvetica Neue" , Helvetica , Arial , sans-serif } code , kbd , pre { font-family : "Roboto Mono" , "Courier New" , Courier , monospace } < / style >
< link rel = "stylesheet" href = "../assets/fonts/material-icons.css" >
< / head >
< body dir = "ltr" >
< svg class = "md-svg" >
< defs >
2019-09-06 19:34:01 +02:00
2020-04-01 03:37:22 +02:00
< / defs >
< / svg >
< input class = "md-toggle" data-md-toggle = "drawer" type = "checkbox" id = "__drawer" autocomplete = "off" >
< input class = "md-toggle" data-md-toggle = "search" type = "checkbox" id = "__search" autocomplete = "off" >
< label class = "md-overlay" data-md-component = "overlay" for = "__drawer" > < / label >
< a href = "#examples" tabindex = "0" class = "md-skip" >
Skip to content
< / a >
< header class = "md-header" data-md-component = "header" >
< nav class = "md-header-nav md-grid" >
< div class = "md-flex" >
< div class = "md-flex__cell md-flex__cell--shrink" >
< a href = ".." title = "IXWebSocket" aria-label = "IXWebSocket" class = "md-header-nav__button md-logo" >
< i class = "md-icon" > < / i >
< / a >
< / div >
< div class = "md-flex__cell md-flex__cell--shrink" >
< label class = "md-icon md-icon--menu md-header-nav__button" for = "__drawer" > < / label >
< / div >
< div class = "md-flex__cell md-flex__cell--stretch" >
< div class = "md-flex__ellipsis md-header-nav__title" data-md-component = "title" >
< span class = "md-header-nav__topic" >
IXWebSocket
< / span >
< span class = "md-header-nav__topic" >
Examples
< / span >
< / div >
< / div >
< div class = "md-flex__cell md-flex__cell--shrink" >
2019-09-06 19:34:01 +02:00
2020-04-01 03:37:22 +02:00
< label class = "md-icon md-icon--search md-header-nav__button" for = "__search" > < / label >
< div class = "md-search" data-md-component = "search" role = "dialog" >
< label class = "md-search__overlay" for = "__search" > < / label >
< div class = "md-search__inner" role = "search" >
< form class = "md-search__form" name = "search" >
< input type = "text" class = "md-search__input" aria-label = "search" name = "query" placeholder = "Search" autocapitalize = "off" autocorrect = "off" autocomplete = "off" spellcheck = "false" data-md-component = "query" data-md-state = "active" >
< label class = "md-icon md-search__icon" for = "__search" > < / label >
< button type = "reset" class = "md-icon md-search__icon" data-md-component = "reset" tabindex = "-1" >

< / button >
< / form >
< div class = "md-search__output" >
< div class = "md-search__scrollwrap" data-md-scrollfix >
< div class = "md-search-result" data-md-component = "result" >
< div class = "md-search-result__meta" >
Type to start searching
< / div >
< ol class = "md-search-result__list" > < / ol >
2019-09-06 19:34:01 +02:00
< / div >
2020-04-01 03:37:22 +02:00
< / div >
2020-02-23 18:49:35 +01:00
< / div >
2020-04-01 03:37:22 +02:00
< / div >
< / div >
< / div >
< / div >
< / nav >
< / header >
2020-02-23 18:49:35 +01:00
2020-04-01 03:37:22 +02:00
< div class = "md-container" >
< main class = "md-main" role = "main" >
< div class = "md-main__inner md-grid" data-md-component = "container" >
2020-02-23 18:49:35 +01:00
2020-04-01 03:37:22 +02:00
< div class = "md-sidebar md-sidebar--primary" data-md-component = "navigation" >
< div class = "md-sidebar__scrollwrap" >
< div class = "md-sidebar__inner" >
< nav class = "md-nav md-nav--primary" data-md-level = "0" >
< label class = "md-nav__title md-nav__title--site" for = "__drawer" >
< a href = ".." title = "IXWebSocket" class = "md-nav__button md-logo" >
< i class = "md-icon" > < / i >
< / a >
IXWebSocket
< / label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = ".." title = "Home" class = "md-nav__link" >
Home
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../CHANGELOG/" title = "Changelog" class = "md-nav__link" >
Changelog
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../build/" title = "Build" class = "md-nav__link" >
Build
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../cobra/" title = "Cobra" class = "md-nav__link" >
Cobra
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../design/" title = "Design" class = "md-nav__link" >
Design
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../packages/" title = "Packages" class = "md-nav__link" >
Packages
< / a >
< / li >
< li class = "md-nav__item md-nav__item--active" >
< input class = "md-toggle md-nav__toggle" data-md-toggle = "toc" type = "checkbox" id = "__toc" >
< label class = "md-nav__link md-nav__link--active" for = "__toc" >
Examples
< / label >
< a href = "./" title = "Examples" class = "md-nav__link md-nav__link--active" >
Examples
< / a >
< nav class = "md-nav md-nav--secondary" >
< label class = "md-nav__title" for = "__toc" > Table of contents< / label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "#windows-note" class = "md-nav__link" >
Windows note
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#websocket-client-api" class = "md-nav__link" >
WebSocket client API
< / a >
< nav class = "md-nav" >
< ul class = "md-nav__list" >
< li class = "md-nav__item" >
< a href = "#sending-messages" class = "md-nav__link" >
Sending messages
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#readystate" class = "md-nav__link" >
ReadyState
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#open-and-close-notifications" class = "md-nav__link" >
Open and Close notifications
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#error-notification" class = "md-nav__link" >
Error notification
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#start-stop" class = "md-nav__link" >
start, stop
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#configuring-the-remote-url" class = "md-nav__link" >
Configuring the remote url
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#pingpong-support" class = "md-nav__link" >
Ping/Pong support
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#heartbeat" class = "md-nav__link" >
Heartbeat.
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#supply-extra-http-headers" class = "md-nav__link" >
Supply extra HTTP headers.
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#subprotocols" class = "md-nav__link" >
Subprotocols
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#automatic-reconnection" class = "md-nav__link" >
Automatic reconnection
< / a >
< / li >
< / ul >
< / nav >
< / li >
< li class = "md-nav__item" >
< a href = "#websocket-server-api" class = "md-nav__link" >
WebSocket server API
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#http-client-api" class = "md-nav__link" >
HTTP client API
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#http-server-api" class = "md-nav__link" >
HTTP server API
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#tls-support-and-configuration" class = "md-nav__link" >
TLS support and configuration
< / a >
< / li >
< / ul >
< / nav >
< / li >
< li class = "md-nav__item" >
< a href = "../ws/" title = "Ws" class = "md-nav__link" >
Ws
< / a >
< / li >
2019-09-06 19:34:01 +02:00
2020-04-01 03:37:22 +02:00
< / ul >
< / nav >
< / div >
< / div >
< / div >
< div class = "md-sidebar md-sidebar--secondary" data-md-component = "toc" >
< div class = "md-sidebar__scrollwrap" >
< div class = "md-sidebar__inner" >
< nav class = "md-nav md-nav--secondary" >
< label class = "md-nav__title" for = "__toc" > Table of contents< / label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "#windows-note" class = "md-nav__link" >
Windows note
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#websocket-client-api" class = "md-nav__link" >
WebSocket client API
< / a >
< nav class = "md-nav" >
< ul class = "md-nav__list" >
< li class = "md-nav__item" >
< a href = "#sending-messages" class = "md-nav__link" >
Sending messages
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#readystate" class = "md-nav__link" >
ReadyState
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#open-and-close-notifications" class = "md-nav__link" >
Open and Close notifications
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#error-notification" class = "md-nav__link" >
Error notification
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#start-stop" class = "md-nav__link" >
start, stop
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#configuring-the-remote-url" class = "md-nav__link" >
Configuring the remote url
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#pingpong-support" class = "md-nav__link" >
Ping/Pong support
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#heartbeat" class = "md-nav__link" >
Heartbeat.
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#supply-extra-http-headers" class = "md-nav__link" >
Supply extra HTTP headers.
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#subprotocols" class = "md-nav__link" >
Subprotocols
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#automatic-reconnection" class = "md-nav__link" >
Automatic reconnection
< / a >
< / li >
< / ul >
< / nav >
< / li >
< li class = "md-nav__item" >
< a href = "#websocket-server-api" class = "md-nav__link" >
WebSocket server API
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#http-client-api" class = "md-nav__link" >
HTTP client API
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#http-server-api" class = "md-nav__link" >
HTTP server API
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#tls-support-and-configuration" class = "md-nav__link" >
TLS support and configuration
< / a >
< / li >
< / ul >
< / nav >
< / div >
< / div >
< / div >
< div class = "md-content" >
< article class = "md-content__inner md-typeset" >
< h1 id = "examples" > Examples< / h1 >
2019-09-06 19:34:01 +02:00
< p > The < a href = "https://github.com/machinezone/IXWebSocket/tree/master/ws" > < em > ws< / em > < / a > folder countains many interactive programs for chat, < a href = "https://github.com/machinezone/IXWebSocket/blob/master/ws/ws_send.cpp" > file transfers< / a > , < a href = "https://github.com/machinezone/IXWebSocket/blob/master/ws/ws_http_client.cpp" > curl like< / a > http clients, demonstrating client and server usage.< / p >
< h2 id = "windows-note" > Windows note< / h2 >
< p > To use the network system on Windows, you need to initialize it once with < em > WSAStartup()< / em > and clean it up with < em > WSACleanup()< / em > . We have helpers for that which you can use, see below. This init would typically take place in your main function.< / p >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > #include < ixwebsocket/IXNetSystem.h>
2019-09-06 19:34:01 +02:00
int main()
{
ix::initNetSystem();
...
ix::uninitNetSystem();
return 0;
}
< / code > < / pre >
< h2 id = "websocket-client-api" > WebSocket client API< / h2 >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > #include < ixwebsocket/IXWebSocket.h>
2019-09-06 19:34:01 +02:00
...
2019-12-03 18:28:36 +01:00
// Our websocket object
2019-09-06 19:34:01 +02:00
ix::WebSocket webSocket;
std::string url(" ws://localhost:8080/" );
webSocket.setUrl(url);
// Optional heart beat, sent every 45 seconds when there is not any traffic
// to make sure that load balancers do not kill an idle connection.
2020-04-01 03:37:22 +02:00
webSocket.setPingInterval(45);
2019-09-06 19:34:01 +02:00
// Per message deflate connection is enabled by default. You can tweak its parameters or disable it
webSocket.disablePerMessageDeflate();
// Setup a callback to be fired when a message or an event (open, close, error) is received
webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
{
if (msg-> type == ix::WebSocketMessageType::Message)
{
std::cout < < msg-> str < < std::endl;
}
}
);
// Now that our callback is setup, we can start our background thread and receive messages
webSocket.start();
// Send a message to the server (default to TEXT mode)
webSocket.send(" hello world" );
// The message can be sent in BINARY mode (useful if you send MsgPack data for example)
webSocket.sendBinary(" some serialized binary data" );
// ... finally ...
// Stop the connection
webSocket.stop()
< / code > < / pre >
< h3 id = "sending-messages" > Sending messages< / h3 >
< p > < code > websocket.send("foo")< / code > will send a message.< / p >
< p > If the connection was closed and sending failed, the return value will be set to false.< / p >
< h3 id = "readystate" > ReadyState< / h3 >
< p > < code > getReadyState()< / code > returns the state of the connection. There are 4 possible states.< / p >
< ol >
< li > ReadyState::Connecting - The connection is not yet open.< / li >
< li > ReadyState::Open - The connection is open and ready to communicate.< / li >
< li > ReadyState::Closing - The connection is in the process of closing.< / li >
< li > ReadyState::Closed - The connection is closed or could not be opened.< / li >
< / ol >
< h3 id = "open-and-close-notifications" > Open and Close notifications< / h3 >
2019-12-03 18:28:36 +01:00
< p > The onMessage event will be fired when the connection is opened or closed. This is similar to the < a href = "https://developer.mozilla.org/en-US/docs/Web/API/WebSocket" > JavaScript browser API< / a > , which has < code > open< / code > and < code > close< / code > events notification that can be registered with the browser < code > addEventListener< / code > .< / p >
< pre > < code class = "cpp" > webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
2019-09-06 19:34:01 +02:00
{
if (msg-> type == ix::WebSocketMessageType::Open)
{
std::cout < < " send greetings" < < std::endl;
// Headers can be inspected (pairs of string/string)
std::cout < < " Handshake Headers:" < < std::endl;
for (auto it : msg-> headers)
{
std::cout < < it.first < < " : " < < it.second < < std::endl;
}
}
else if (msg-> type == ix::WebSocketMessageType::Close)
{
std::cout < < " disconnected" < < std::endl;
// The server can send an explicit code and reason for closing.
// This data can be accessed through the closeInfo object.
std::cout < < msg-> closeInfo.code < < std::endl;
std::cout < < msg-> closeInfo.reason < < std::endl;
}
}
);
< / code > < / pre >
< h3 id = "error-notification" > Error notification< / h3 >
< p > A message will be fired when there is an error with the connection. The message type will be < code > ix::WebSocketMessageType::Error< / code > . Multiple fields will be available on the event to describe the error.< / p >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
2019-09-06 19:34:01 +02:00
{
if (msg-> type == ix::WebSocketMessageType::Error)
{
std::stringstream ss;
ss < < " Error: " < < msg-> errorInfo.reason < < std::endl;
ss < < " #retries: " < < msg-> eventInfo.retries < < std::endl;
ss < < " Wait time(ms): " < < msg-> eventInfo.wait_time < < std::endl;
ss < < " HTTP Status: " < < msg-> eventInfo.http_status < < std::endl;
std::cout < < ss.str() < < std::endl;
}
}
);
< / code > < / pre >
< h3 id = "start-stop" > start, stop< / h3 >
< ol >
< li > < code > websocket.start()< / code > connect to the remote server and starts the message receiving background thread.< / li >
< li > < code > websocket.stop()< / code > disconnect from the remote server and closes the background thread.< / li >
< / ol >
< h3 id = "configuring-the-remote-url" > Configuring the remote url< / h3 >
< p > The url can be set and queried after a websocket object has been created. You will have to call < code > stop< / code > and < code > start< / code > if you want to disconnect and connect to that new url.< / p >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > std::string url(" wss://example.com" );
2019-09-06 19:34:01 +02:00
websocket.configure(url);
< / code > < / pre >
< h3 id = "pingpong-support" > Ping/Pong support< / h3 >
< p > Ping/pong messages are used to implement keep-alive. 2 message types exists to identify ping and pong messages. Note that when a ping message is received, a pong is instantly send back as requested by the WebSocket spec.< / p >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
2019-09-06 19:34:01 +02:00
{
if (msg-> type == ix::WebSocketMessageType::Ping ||
msg-> type == ix::WebSocketMessageType::Pong)
{
std::cout < < " pong data: " < < msg-> str < < std::endl;
}
}
);
< / code > < / pre >
< p > A ping message can be sent to the server, with an optional data string.< / p >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > websocket.ping(" ping data, optional (empty string is ok): limited to 125 bytes long" );
2019-09-06 19:34:01 +02:00
< / code > < / pre >
< h3 id = "heartbeat" > Heartbeat.< / h3 >
< p > You can configure an optional heart beat / keep-alive, sent every 45 seconds
when there is no any traffic to make sure that load balancers do not kill an
idle connection.< / p >
2020-04-01 03:37:22 +02:00
< pre > < code class = "cpp" > webSocket.setPingInterval(45);
2019-09-06 19:34:01 +02:00
< / code > < / pre >
< h3 id = "supply-extra-http-headers" > Supply extra HTTP headers.< / h3 >
< p > You can set extra HTTP headers to be sent during the WebSocket handshake.< / p >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > WebSocketHttpHeaders headers;
2019-09-06 19:34:01 +02:00
headers[" foo" ] = " bar" ;
webSocket.setExtraHeaders(headers);
< / code > < / pre >
2019-10-16 20:19:27 +02:00
< h3 id = "subprotocols" > Subprotocols< / h3 >
< p > You can specify subprotocols to be set during the WebSocket handshake. For more info you can refer to < a href = "https://hpbn.co/websocket/#subprotocol-negotiation" > this doc< / a > .< / p >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > webSocket.addSubprotocol(" appProtocol-v1" );
2019-10-16 20:19:27 +02:00
webSocket.addSubprotocol(" appProtocol-v2" );
< / code > < / pre >
< p > The protocol that the server did accept is available in the open info < code > protocol< / code > field.< / p >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > std::cout < < " protocol: " < < msg-> openInfo.protocol < < std::endl;
2019-10-16 20:19:27 +02:00
< / code > < / pre >
2019-09-06 19:34:01 +02:00
< h3 id = "automatic-reconnection" > Automatic reconnection< / h3 >
< p > Automatic reconnection kicks in when the connection is disconnected without the user consent. This feature is on by default and can be turned off.< / p >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > webSocket.enableAutomaticReconnection(); // turn on
2019-09-06 19:34:01 +02:00
webSocket.disableAutomaticReconnection(); // turn off
bool enabled = webSocket.isAutomaticReconnectionEnabled(); // query state
< / code > < / pre >
< p > The technique to calculate wait time is called < a href = "https://docs.aws.amazon.com/general/latest/gr/api-retries.html" > exponential
backoff< / a > . Here
are the default waiting times between attempts (from connecting with < code > ws connect ws://foo.com< / code > )< / p >
< pre > < code > > Connection error: Got bad status connecting to foo.com, status: 301, HTTP Status line: HTTP/1.1 301 Moved Permanently
#retries: 1
Wait time(ms): 100
#retries: 2
Wait time(ms): 200
#retries: 3
Wait time(ms): 400
#retries: 4
Wait time(ms): 800
#retries: 5
Wait time(ms): 1600
#retries: 6
Wait time(ms): 3200
#retries: 7
Wait time(ms): 6400
#retries: 8
Wait time(ms): 10000
< / code > < / pre >
< p > The waiting time is capped by default at 10s between 2 attempts, but that value can be changed and queried.< / p >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > webSocket.setMaxWaitBetweenReconnectionRetries(5 * 1000); // 5000ms = 5s
2019-09-06 19:34:01 +02:00
uint32_t m = webSocket.getMaxWaitBetweenReconnectionRetries();
< / code > < / pre >
< h2 id = "websocket-server-api" > WebSocket server API< / h2 >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > #include < ixwebsocket/IXWebSocketServer.h>
2019-09-06 19:34:01 +02:00
...
// Run a server on localhost at a given port.
// Bound host name, max connections and listen backlog can also be passed in as parameters.
ix::WebSocketServer server(port);
server.setOnConnectionCallback(
[& server](std::shared_ptr< WebSocket> webSocket,
std::shared_ptr< ConnectionState> connectionState)
{
webSocket-> setOnMessageCallback(
[webSocket, connectionState, & server](const ix::WebSocketMessagePtr msg)
{
if (msg-> type == ix::WebSocketMessageType::Open)
{
std::cerr < < " New connection" < < std::endl;
// A connection state object is available, and has a default id
// You can subclass ConnectionState and pass an alternate factory
// to override it. It is useful if you want to store custom
// attributes per connection (authenticated bool flag, attributes, etc...)
std::cerr < < " id: " < < connectionState-> getId() < < std::endl;
// The uri the client did connect to.
std::cerr < < " Uri: " < < msg-> openInfo.uri < < std::endl;
std::cerr < < " Headers:" < < std::endl;
for (auto it : msg-> openInfo.headers)
{
std::cerr < < it.first < < " : " < < it.second < < std::endl;
}
}
else if (msg-> type == ix::WebSocketMessageType::Message)
{
// For an echo server, we just send back to the client whatever was received by the server
// All connected clients are available in an std::set. See the broadcast cpp example.
// Second parameter tells whether we are sending the message in binary or text mode.
// Here we send it in the same mode as it was received.
webSocket-> send(msg-> str, msg-> binary);
}
}
);
}
);
auto res = server.listen();
if (!res.first)
{
// Error handling
return 1;
}
// Run the server in the background. Server can be stoped by calling server.stop()
server.start();
// Block until server.stop() is called.
server.wait();
< / code > < / pre >
< h2 id = "http-client-api" > HTTP client API< / h2 >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > #include < ixwebsocket/IXHttpClient.h>
2019-09-06 19:34:01 +02:00
...
//
// Preparation
//
HttpClient httpClient;
HttpRequestArgsPtr args = httpClient.createRequest();
// Custom headers can be set
WebSocketHttpHeaders headers;
headers[" Foo" ] = " bar" ;
args-> extraHeaders = headers;
// Timeout options
args-> connectTimeout = connectTimeout;
args-> transferTimeout = transferTimeout;
// Redirect options
args-> followRedirects = followRedirects;
args-> maxRedirects = maxRedirects;
// Misc
args-> compress = compress; // Enable gzip compression
args-> verbose = verbose;
args-> logger = [](const std::string& msg)
{
std::cout < < msg;
};
//
// Synchronous Request
//
HttpResponsePtr out;
std::string url = " https://www.google.com" ;
// HEAD request
out = httpClient.head(url, args);
// GET request
out = httpClient.get(url, args);
// POST request with parameters
HttpParameters httpParameters;
httpParameters[" foo" ] = " bar" ;
out = httpClient.post(url, httpParameters, args);
// POST request with a body
out = httpClient.post(url, std::string(" foo=bar" ), args);
//
// Result
//
auto statusCode = response-> statusCode; // Can be HttpErrorCode::Ok, HttpErrorCode::UrlMalformed, etc...
auto errorCode = response-> errorCode; // 200, 404, etc...
auto responseHeaders = response-> headers; // All the headers in a special case-insensitive unordered_map of (string, string)
auto payload = response-> payload; // All the bytes from the response as an std::string
auto errorMsg = response-> errorMsg; // Descriptive error message in case of failure
auto uploadSize = response-> uploadSize; // Byte count of uploaded data
auto downloadSize = response-> downloadSize; // Byte count of downloaded data
//
// Asynchronous Request
//
bool async = true;
HttpClient httpClient(async);
auto args = httpClient.createRequest(url, HttpClient::kGet);
// Push the request to a queue,
bool ok = httpClient.performRequest(args, [](const HttpResponsePtr& response)
{
// This callback execute in a background thread. Make sure you uses appropriate protection such as mutex
auto statusCode = response-> statusCode; // acess results
}
);
// ok will be false if your httpClient is not async
< / code > < / pre >
< h2 id = "http-server-api" > HTTP server API< / h2 >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > #include < ixwebsocket/IXHttpServer.h>
2019-09-06 19:34:01 +02:00
ix::HttpServer server(port, hostname);
auto res = server.listen();
if (!res.first)
{
std::cerr < < res.second < < std::endl;
return 1;
}
server.start();
server.wait();
< / code > < / pre >
< p > If you want to handle how requests are processed, implement the setOnConnectionCallback callback, which takes an HttpRequestPtr as input, and returns an HttpResponsePtr. You can look at HttpServer::setDefaultConnectionCallback for a slightly more advanced callback example.< / p >
2019-12-03 18:28:36 +01:00
< pre > < code class = "cpp" > setOnConnectionCallback(
2019-09-06 19:34:01 +02:00
[this](HttpRequestPtr request,
std::shared_ptr< ConnectionState> /*connectionState*/) -> HttpResponsePtr
{
// Build a string for the response
std::stringstream ss;
ss < < request-> method
< < " "
< < request-> uri;
std::string content = ss.str();
return std::make_shared< HttpResponse> (200, " OK" ,
HttpErrorCode::Ok,
WebSocketHttpHeaders(),
content);
}
2020-03-17 18:09:52 +01:00
< / code > < / pre >
< h2 id = "tls-support-and-configuration" > TLS support and configuration< / h2 >
< p > To leverage TLS features, the library must be compiled with the option < code > USE_TLS=1< / code > .< / p >
< p > Then, secure sockets are automatically used when connecting to a < code > wss://*< / code > url.< / p >
< p > Additional TLS options can be configured by passing a < code > ix::SocketTLSOptions< / code > instance to the
< code > setTLSOptions< / code > on < code > ix::WebSocket< / code > (or < code > ix::WebSocketServer< / code > or < code > ix::HttpServer< / code > )< / p >
< pre > < code class = "cpp" > webSocket.setTLSOptions({
.certFile = " path/to/cert/file.pem" ,
.keyFile = " path/to/key/file.pem" ,
.caFile = " path/to/trust/bundle/file.pem" ,
.tls = true // required in server mode
});
< / code > < / pre >
< p > Specifying < code > certFile< / code > and < code > keyFile< / code > configures the certificate that will be used to communicate with TLS peers.< / p >
< p > On a client, this is only necessary for connecting to servers that require a client certificate.< / p >
< p > On a server, this is necessary for TLS support.< / p >
< p > Specifying < code > caFile< / code > configures the trusted roots bundle file (in PEM format) that will be used to verify peer certificates.
- The special value of < code > SYSTEM< / code > (the default) indicates that the system-configured trust bundle should be used; this is generally what you want when connecting to any publicly exposed API/server.
- The special value of < code > NONE< / code > can be used to disable peer verification; this is only recommended to rule out certificate verification when testing connectivity.< / p >
< p > For a client, specifying < code > caFile< / code > can be used if connecting to a server that uses a self-signed cert, or when using a custom CA in an internal environment.< / p >
< p > For a server, specifying < code > caFile< / code > implies that:
1. You require clients to present a certificate
2020-04-01 03:37:22 +02:00
1. It must be signed by one of the trusted roots in the file< / p >
< / article >
< / div >
2019-09-06 19:34:01 +02:00
< / div >
2020-04-01 03:37:22 +02:00
< / main >
< footer class = "md-footer" >
< div class = "md-footer-nav" >
< nav class = "md-footer-nav__inner md-grid" >
< a href = "../packages/" title = "Packages" class = "md-flex md-footer-nav__link md-footer-nav__link--prev" rel = "prev" >
< div class = "md-flex__cell md-flex__cell--shrink" >
< i class = "md-icon md-icon--arrow-back md-footer-nav__button" > < / i >
2019-09-06 19:34:01 +02:00
< / div >
2020-04-01 03:37:22 +02:00
< div class = "md-flex__cell md-flex__cell--stretch md-footer-nav__title" >
< span class = "md-flex__ellipsis" >
< span class = "md-footer-nav__direction" >
Previous
< / span >
Packages
< / span >
2019-09-06 19:34:01 +02:00
< / div >
2020-04-01 03:37:22 +02:00
< / a >
< a href = "../ws/" title = "Ws" class = "md-flex md-footer-nav__link md-footer-nav__link--next" rel = "next" >
< div class = "md-flex__cell md-flex__cell--stretch md-footer-nav__title" >
< span class = "md-flex__ellipsis" >
< span class = "md-footer-nav__direction" >
Next
< / span >
Ws
< / span >
2019-09-06 19:34:01 +02:00
< / div >
2020-04-01 03:37:22 +02:00
< div class = "md-flex__cell md-flex__cell--shrink" >
< i class = "md-icon md-icon--arrow-forward md-footer-nav__button" > < / i >
2019-09-06 19:34:01 +02:00
< / div >
2020-04-01 03:37:22 +02:00
< / a >
< / nav >
2019-09-06 19:34:01 +02:00
< / div >
2020-04-01 03:37:22 +02:00
< div class = "md-footer-meta md-typeset" >
< div class = "md-footer-meta__inner md-grid" >
< div class = "md-footer-copyright" >
powered by
< a href = "https://www.mkdocs.org" target = "_blank" rel = "noopener" > MkDocs< / a >
and
< a href = "https://squidfunk.github.io/mkdocs-material/" target = "_blank" rel = "noopener" >
Material for MkDocs< / a >
< / div >
< / div >
< / div >
< / footer >
< / div >
< script src = "../assets/javascripts/application.c33a9706.js" > < / script >
< script > app . initialize ( { version : "1.1" , url : { base : ".." } } ) < / script >
< / body >
< / html >