Equivalent WebSocket server and client implementations across 12 programming languages
Learn WebSocket and RFC 6455 internals through one shared binary protocol with CI-verified cross-language interoperability — Java, Kotlin, Python, Go, Rust, C++, C#, Dart, PHP, Swift, Node.js, and TypeScript
The sibling of hello-grpc: where hello-grpc shares a contract through protoc-generated stubs, this project hand-rolls one binary protocol as 12 language-native codecs — any client talks to any server, 12 × 12 combinations.
This repository demonstrates comparable WebSocket implementations across 12 programming languages, with Docker, docker-compose orchestration, shared protocol test vectors, and a fully automated dependency pipeline. It is a learning and interoperability repository rather than a drop-in production platform.
Each implementation ships both a server and a client, covers the same 13 message types defined in the shared binary contract PROTOCOL.md, and is exercised by the same CI pipeline. Audited per-language details live in the feature parity matrix.
| No. | Language | WebSocket Library | Build System | Recommended IDE |
|---|---|---|---|---|
| 1 | C++ | dependency-free RFC 6455 layer | CMake | CLion |
| 2 | Rust | tokio-tungstenite | Cargo | RustRover |
| 3 | Java | Java-WebSocket | Maven | IntelliJ IDEA |
| 4 | Go | gorilla/websocket | Go Modules | GoLand |
| 5 | C# | System.Net.WebSockets | dotnet / NuGet | Rider |
| 6 | Python | websockets | pip | PyCharm |
| 7 | Node.js | ws | npm | WebStorm |
| 8 | TypeScript | ws + tsc | npm | WebStorm |
| 9 | Dart | dart:io WebSocket | Pub | Android Studio |
| 10 | Kotlin | Ktor WebSockets | Gradle | IntelliJ IDEA |
| 11 | Swift | dependency-free socket / RFC 6455 layer | SwiftPM | Xcode |
| 12 | PHP | Ratchet server + Pawl client | Composer | PhpStorm |
Every implementation exercises the same six flows on the canonical endpoint ws://<host>:9898/ws:
- Handshake — client announces its language (HELLO), server answers with its own (BONJOUR)
- Echo — request/response with correlated ids (ECHO_REQUEST / ECHO_RESPONSE)
- Kiss — server asks for OS info, client replies with locale (KISS_REQUEST / KISS_RESPONSE)
- Heartbeat — application-level PING/PONG every 1s, 60s session timeout
- Time broadcast — server pushes TIME_NOTIFICATION every 5s
- Random to hash — client pushes RANDOM_NUMBER every 5s, server replies with a SHA-256 HASH_RESPONSE
Each binary WebSocket message carries exactly one protocol frame:
Offset Size Field
0 1 MAGIC 0x48 ('H')
1 1 VERSION 0x01
2 1 MSG_TYPE
3 1 FLAGS
4 4 PAYLOAD_LEN uint32 big-endian
8 N PAYLOAD
The protocol supports HELLO/BONJOUR, echo, application heartbeat, time notification, OS/locale exchange, random-number hashing, disconnect, and typed errors. Frames are limited to 1 MiB. The canonical contract, including a byte-level worked example, is PROTOCOL.md.
| Language | Server | Client | Full Protocol | Codec Tests | Docker | Compose | Cross-language Smoke |
|---|---|---|---|---|---|---|---|
| C++ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Rust | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Java | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Go | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| C# | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Python | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Node.js | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| TypeScript | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Dart | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Kotlin | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Swift | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| PHP | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
TLS (wss://), authentication, and rate limiting are intentionally out of
scope — see Security Scope. How each cell is verified is
documented in docs/PARITY_MATRIX.md.
| Variable | Default | Purpose |
|---|---|---|
WS_SERVER |
127.0.0.1 |
Client target host |
WS_PORT |
9898 |
Server/client port |
WS_PATH |
/ws |
WebSocket endpoint path |
Each language directory contains scripts/build.sh. Examples:
./hello-websocket-go/scripts/build.sh
./hello-websocket-python/scripts/build.sh
./hello-websocket-java/scripts/build.sh
./hello-websocket-rust/scripts/build.shThe CI workflow builds and tests every implementation. Codec tests cover the worked example, all message types, malformed frames, signed integer boundaries, and multilingual UTF-8. Canonical vectors are shared across all 12 languages via tests/protocol-vectors.json, with tests/reference_client.py as the reference peer. Docker smoke tests verify HELLO/BONJOUR and PING/PONG across languages.
Dependency updates are managed across all ecosystems by Dependabot, dependency review, OSV scanning, and guarded auto-merge. See docs/DEPENDENCY_AUTOMATION.md.
Start a server and client in separate terminals:
./hello-websocket-python/scripts/run-server.sh
./hello-websocket-go/scripts/run-client.shAll clients and servers share the same endpoint and wire protocol, so any
server can be combined with any client — 12 servers × 12 clients. Set
WS_SERVER, WS_PORT, or WS_PATH when required.
cd docker
./build_image.sh --language java
./run_container.sh --language java --component server
./run_container.sh --language go --component client
./smoke_test_all.sh --server javaPer-language multi-stage Dockerfiles (Dockerfile.<lang>) build
feuyeux/ws_server_<lang> and feuyeux/ws_client_<lang> images, and
docker-compose.yml plus 12 per-language docker-compose.<lang>.yml files
provide one-command orchestration. Set IMAGE_TAG to build, run, or push a
tag other than 1.0.0.
This repository is an interoperability and teaching project. The included
servers use plain ws://; they do not implement authentication or
authorization, and userId is untrusted display metadata.
For deployment outside a trusted network, terminate TLS at a reverse proxy, authenticate the upgrade request, restrict browser Origins, rate-limit connections/messages, and run containers with an appropriate non-root policy.
Star history: star-history.com/#feuyeux/hello-websocket. The live embed was removed because GitHub now restricts the stargazer timeline API to repository collaborators, so third-party star charts cannot render without an owner-supplied token (details).