- All C++ WebSocket Client Server
- Description
- Dependencies
- How to Build
- How to Run
- Thanks for watching!
C++ Client-Server example
- is written in C++ and compiled to WebAssembly
- which offer the (currently) highest performance possible within a browser
1.7x slower than native speed
or ~5-6 times faster than JavaScript
(also devoid of GC slowdown)
- which offer the (currently) highest performance possible within a browser
- will connect to the server with a websocket inside the WebAssembly logic
- the connection is established using a config fetched from the server-side (easily configured if needed)
a native version
of the client is also availablemostly for
faster development anddebug purpose
:- tools like gdb and valgrind become available
- the network part rely on the Network Wrapper
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#242424',
'primaryTextColor': '#DDD',
'primaryBorderColor': '#000',
'lineColor': '#A0A0A0',
'secondaryColor': '#454545',
'tertiaryColor': '#353535'
}
}
}%%
flowchart TB
subgraph client-side [Client Side]
browser[Browser]
subgraph client-js-app [Web Js App]
direction TB
file_index_html[index.html]
file_bundle_js[bundle.js]
file_index_html -..-> file_bundle_js
end
subgraph client-wasm-app [Web Wasm App]
direction TB
file_index_js[index.js]
file_index_wasm[index.wasm]
file_index_data[index.data]
file_index_js -..-> file_index_wasm
file_index_js -..-> file_index_data
end
subgraph real-time-client-app ["Real Time Client App (Example)"]
direction LR
ws_client[WebSocket<br>Client]
client_game_logic[Game Logic]
client_physic_logic[Physic]
client_graphic_logic[Graphic]
client_game_logic <---> ws_client
client_game_logic <-.-> client_physic_logic
client_game_logic <-.-> client_graphic_logic
end
browser --- client-js-app
client-js-app --> client-wasm-app
client-wasm-app --- real-time-client-app
client_http_get((HTTP GET))
client_websocket((WebSocket))
client-js-app --- client_http_get
client-wasm-app --- client_http_get
real-time-client-app --- client_websocket
end
- is written in C++ and compiled to a native binary
- the network rely on the Network Wrapper
- the number of thread(s) used can be configured by command line arguments
- recursively explore an asset folder
- open every files (when possible)
- compress the opened files (when possible)
- cache in-memory (hash map)
- compressed files must be smaller to be kept in the cache
- accept and reply to HTTP request (GET)
- handle any custom requests
- used to reply the "web-socket-config.json"
- retrieve the requested file from the cache
- reply the requested file
- if available and supported, will reply the compressed payload
- will set the appropriate content-type header (when supported)
- reply the requested file
- 404 status if the requested file is missing from the in-memory cache
- handle any custom requests
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#242424',
'primaryTextColor': '#DDD',
'primaryBorderColor': '#000',
'lineColor': '#A0A0A0',
'secondaryColor': '#454545',
'tertiaryColor': '#353535'
}
}
}%%
flowchart TD
subgraph server-side [Server Side]
direction LR
server_http_get((HTTP GET))
subgraph server-files [File Server]
http_server[HTTP Server]
direction LR
server_file_cache[File Cache]
server_file_disk[Disk]
http_server <---> server_file_cache
server_file_cache <-.-> server_file_disk
end
server_http_get --- server-files
end
- event(s)
- accept connection(s)
- register the new user
- broadcast "new user" to all users
- new message(s)
- read messages
- broadcast "new message" to all users
- disconnection
- remove the lost user
- broadcast "disconnected user" to all users
- accept connection(s)
- a thread safe session manager is included
- a
shared mutex
is used- multiple read will rely on
shared lock(s)
- unique write will rely on
unique lock(s)
- multiple read will rely on
- a
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#242424',
'primaryTextColor': '#DDD',
'primaryBorderColor': '#000',
'lineColor': '#A0A0A0',
'secondaryColor': '#454545',
'tertiaryColor': '#353535'
}
}
}%%
flowchart TD
subgraph server-side [Server Side]
direction LR
server_websocket((WebSocket))
subgraph real-time-server-app ["Real Time Server App (Example)"]
direction LR
ws_server[WebSocket<br>Server]
server_game_logic[Game Logic]
server_physic_logic[Physic]
ws_server <---> server_game_logic
server_game_logic <-.-> server_physic_logic
end
server_websocket --- real-time-server-app
end
-
is written in C++ and compiled to a native archive or a wasm bytecode
- the native part contains
- an abstracted http server
- host, port, total-threads (boost::strand if 2 or more threads)
- an abstracted websocket server
- host, port, total-threads (boost::strand if 2 or more threads)
- an abstracted websocket client
- rely on boost beast websocket
- use a worker thread
- an abstracted http server
- the wasm part contains
- an abstracted websocket client
- rely on emscripten websocket
- an abstracted websocket client
- the native part contains
-
the native parts rely on boost Asio beast
- rely on boost executor(s)
- which in turn, rely on boost strand
- rely on boost executor(s)
-
benefit(s) of the wrapper
- easily reusable
- make boost (very) slow compilation happens only once
- allow the client-side to work in native and wasm with nearly the same code
-
all of the network code is abstracted and located in the network-wrapper
- native wrapper: native archive (static library)
- wasm wrapper: wasm bytecode (static library)
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#242424',
'primaryTextColor': '#DDD',
'primaryBorderColor': '#000',
'lineColor': '#A0A0A0',
'secondaryColor': '#454545',
'tertiaryColor': '#353535'
}
}
}%%
mindmap
root(("network<br>wrapper"))
http_server)"http server"(
ws_server)"websocket<br>server"(
ws_client)"websocket<br>native/wasm<br>client"(
- Emscripten 3.1.44
- This will be locally installed (cloned and setup) if not detected
- the 3.1.44 version will be ensured, even if already present
- NodeJs
- g++ (build-essential)
- libzstd1
- libboost1.71-dev
chmod +x ./sh_build_everything.sh
./sh_build_everything.sh
# will:
# -> build the client C++ application (wasm)
# -> build the client TypeScript wasm-loader (JavaScript)
# -> build the server C++ application (binary)
# -> copy the client files in the server asset folder
# -> run the server
# -> http-port: 777
# -> ws-port: 8888
# -> threads all at 1
# the server need to be started from the "./server-side" folder
# -> mainly since this is where the "files/" folder is located
cd ./server-side
# ip-address http-port ws-port http-threads ws-threads
./bin/exec 127.0.0.1 7777 8888 1 1
# http://{ip-address}:{http-port}/
http://127.0.0.1:7777/
# to see it in action -> open more tabs with the same url
# -> will log broadcasts of when a new clients join/leave