1063 lines
32 KiB
HTML
1063 lines
32 KiB
HTML
|
|
|
|
|
|
|
|
<!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>
|
|
|
|
|
|
</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">
|
|
|
|
<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>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</nav>
|
|
</header>
|
|
|
|
<div class="md-container">
|
|
|
|
|
|
|
|
|
|
<main class="md-main" role="main">
|
|
<div class="md-main__inner md-grid" data-md-component="container">
|
|
|
|
|
|
<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>
|
|
|
|
|
|
</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>
|
|
<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>
|
|
<pre><code class="cpp">#include <ixwebsocket/IXNetSystem.h>
|
|
|
|
int main()
|
|
{
|
|
ix::initNetSystem();
|
|
|
|
...
|
|
|
|
ix::uninitNetSystem();
|
|
return 0;
|
|
}
|
|
</code></pre>
|
|
|
|
<h2 id="websocket-client-api">WebSocket client API</h2>
|
|
<pre><code class="cpp">#include <ixwebsocket/IXWebSocket.h>
|
|
|
|
...
|
|
|
|
// Our websocket object
|
|
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.
|
|
webSocket.setPingInterval(45);
|
|
|
|
// 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>
|
|
<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)
|
|
{
|
|
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>
|
|
<pre><code class="cpp">webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
|
|
{
|
|
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>
|
|
<pre><code class="cpp">std::string url("wss://example.com");
|
|
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>
|
|
<pre><code class="cpp">webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
|
|
{
|
|
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>
|
|
<pre><code class="cpp">websocket.ping("ping data, optional (empty string is ok): limited to 125 bytes long");
|
|
</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>
|
|
<pre><code class="cpp">webSocket.setPingInterval(45);
|
|
</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>
|
|
<pre><code class="cpp">WebSocketHttpHeaders headers;
|
|
headers["foo"] = "bar";
|
|
webSocket.setExtraHeaders(headers);
|
|
</code></pre>
|
|
|
|
<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>
|
|
<pre><code class="cpp">webSocket.addSubprotocol("appProtocol-v1");
|
|
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>
|
|
<pre><code class="cpp">std::cout << "protocol: " << msg->openInfo.protocol << std::endl;
|
|
</code></pre>
|
|
|
|
<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>
|
|
<pre><code class="cpp">webSocket.enableAutomaticReconnection(); // turn on
|
|
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>
|
|
<pre><code class="cpp">webSocket.setMaxWaitBetweenReconnectionRetries(5 * 1000); // 5000ms = 5s
|
|
uint32_t m = webSocket.getMaxWaitBetweenReconnectionRetries();
|
|
</code></pre>
|
|
|
|
<h2 id="websocket-server-api">WebSocket server API</h2>
|
|
<pre><code class="cpp">#include <ixwebsocket/IXWebSocketServer.h>
|
|
|
|
...
|
|
|
|
// 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>
|
|
<pre><code class="cpp">#include <ixwebsocket/IXHttpClient.h>
|
|
|
|
...
|
|
|
|
//
|
|
// 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>
|
|
<pre><code class="cpp">#include <ixwebsocket/IXHttpServer.h>
|
|
|
|
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>
|
|
<pre><code class="cpp">setOnConnectionCallback(
|
|
[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);
|
|
}
|
|
</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
|
|
1. It must be signed by one of the trusted roots in the file</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</article>
|
|
</div>
|
|
</div>
|
|
</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>
|
|
</div>
|
|
<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>
|
|
</div>
|
|
</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>
|
|
</div>
|
|
<div class="md-flex__cell md-flex__cell--shrink">
|
|
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
|
|
</div>
|
|
</a>
|
|
|
|
</nav>
|
|
</div>
|
|
|
|
<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> |