shsp 1.2.3
shsp: ^1.2.3 copied to clipboard
Single HandShake Protocol (SHSP) - a custom networking protocol for peer-to-peer communication. Unified package containing types, interfaces, and implementations.
SHSP - Single HandShake Protocol #
A high-performance Dart package implementing the Single HandShake Protocol (SHSP) for peer-to-peer communication over UDP. Works seamlessly on backend (Dart/Server), mobile (Flutter), and web platforms.
Features #
- Lightweight Protocol: Minimal overhead for peer-to-peer communication
- Automatic Handshaking: Streamlined connection establishment with configurable timeouts
- Keep-Alive Support: Maintain connections with periodic heartbeat messages
- Pluggable Compression: Built-in support for GZip, LZ4, and Zstd codecs
- Auto-Wiring Classes:
AutoShspPeerandAutoShspInstancefor simplified usage - Global Socket Management:
ShspSocketSingletonfor seamless socket switching - Cross-Platform: Runs on Dart CLI, Flutter mobile, and web
- IPv4/IPv6 Support: Dual-stack ready with automatic address formatting
- Comprehensive Testing: 399+ passing tests ensuring reliability
Installation #
Add to your pubspec.yaml:
dependencies:
shsp: ^1.2.3
Then run:
dart pub get
Quick Start #
Using AutoShspPeer (Recommended) #
The easiest way to get started:
import 'package:shsp/shsp.dart';
import 'dart:typed_data';
// Create a peer
final peer = await AutoShspPeer.create(
remoteInfo: RemoteInfo('192.168.1.100', 8080),
);
// Register message callback
peer.onMessage((message) {
print('Received: $message');
});
// Send data
await peer.sendData(Uint8List.fromList([1, 2, 3]));
// Clean up
await peer.close();
Using AutoShspInstance (With Keep-Alive) #
For longer-lived connections:
final instance = await AutoShspInstance.create(
remoteInfo: RemoteInfo('192.168.1.100', 8080),
keepAliveSeconds: 30,
);
instance.onData((data) {
print('Received data: $data');
});
await instance.sendData(Uint8List.fromList([1, 2, 3]));
await instance.close();
Global Socket Management #
For applications with multiple peers/instances:
// Initialize the singleton with a socket
final socket = await ShspSocket.bind(InternetAddress.anyIPv4, 0);
ShspSocketSingleton.instance = socket;
// Create peers - they automatically use the singleton
final peer1 = await AutoShspPeer.create(remoteInfo: RemoteInfo('192.168.1.100', 8080));
final peer2 = await AutoShspPeer.create(remoteInfo: RemoteInfo('192.168.1.101', 8080));
// Switch socket if needed - all peers reconnect automatically
ShspSocketSingleton.instance = await ShspSocket.bind(InternetAddress.anyIPv4, 0);
Compression #
SHSP supports automatic compression for data messages:
import 'package:shsp/shsp.dart';
// Available compression codecs:
// - GZipCodec: Best compression ratio (slower)
// - LZ4Codec: Fast compression (lower ratio)
// - ZstdCodec: Balanced (recommended)
final peer = await AutoShspPeer.create(
remoteInfo: RemoteInfo('192.168.1.100', 8080),
compressionCodec: GZipCodec(), // Or LZ4Codec(), ZstdCodec()
);
// Compression is automatic for data messages
await peer.sendData(largeData);
IPv4 and IPv6 #
// IPv4
final socket = await ShspSocket.bind(InternetAddress.anyIPv4, 8080);
// IPv6 (dual-stack on most systems)
final socket = await ShspSocket.bind(InternetAddress.anyIPv6, 8080);
// Specific address
final socket = await ShspSocket.bind(InternetAddress('192.168.1.100'), 8080);
Registry Management (v1.2.0+) #
Manage multiple socket and peer instances efficiently:
import 'package:shsp/shsp.dart';
// Create a registry for managing multiple sockets
final socketRegistry = <SocketType, IShspSocket>{};
// Register IPv4 and IPv6 sockets
final ipv4Socket = await ShspSocket.bind(InternetAddress.anyIPv4, 8080);
final ipv6Socket = await ShspSocket.bind(InternetAddress.anyIPv6, 8080);
socketRegistry[SocketType.ipv4] = ipv4Socket;
socketRegistry[SocketType.ipv6] = ipv6Socket;
// Access sockets by type
final activeSocket = socketRegistry[SocketType.ipv4];
// Clean up all sockets
for (final socket in socketRegistry.values) {
socket.destroy();
}
Advanced: Registry Mixin Pattern #
class MyPeerManager with Registry<String, IShspPeer> {
Future<void> createPeer(String id, RemoteInfo remoteInfo) async {
final peer = await AutoShspPeer.create(remoteInfo: remoteInfo);
register(id, peer);
}
Future<void> closePeer(String id) async {
final peer = unregister(id);
if (peer != null) {
await peer.close();
}
}
Future<void> broadcastData(Uint8List data) async {
for (final item in allItems) {
await item.value.sendData(data);
}
}
void cleanupAll() {
destroyAll(); // Calls destroy() on all peers
}
}
// Usage
final manager = MyPeerManager();
await manager.createPeer('peer1', RemoteInfo('192.168.1.100', 8080));
await manager.createPeer('peer2', RemoteInfo('192.168.1.101', 8080));
await manager.broadcastData(Uint8List.fromList([1, 2, 3]));
manager.cleanupAll();
Architecture #
SHSP is organized into three main components:
Types #
Core type definitions:
RemoteInfo: Address and port informationSocketProfile: Socket configuration and stateInstanceProfile: Instance configuration and state- Callback type definitions
Interfaces #
Protocol contracts for extensibility:
- Core:
IShspSocket,IShspPeer,IShspInstance,IShspInstanceHandler - Compression:
ICompressionCodec - Handshake:
IShspHandshake - Factories (for dependency injection):
IShspSocketFactory,IShspPeerFactory,IShspInstanceFactory - Utilities:
IAddressUtility,ICallbackMap<T>,IKeepAliveTimer,IMessageCallbackMap,IRawShspSocket,IDualShspSocket - Singletons:
IMessageCallbackMapSingleton,IShspSocketInfoSingleton
Implementations #
Concrete implementations:
ShspSocket: UDP socket with callback managementShspPeer: Peer protocol implementationShspInstance: Instance with keep-alive supportAutoShspPeer: Auto-wiring peer (recommended for most use cases)AutoShspInstance: Auto-wiring instanceShspSocketSingleton: Global socket management- Compression codecs:
GZipCodec,LZ4Codec,ZstdCodec
Registry Utilities (v1.2.0+) #
Advanced instance management:
Registry<Key, Value>: Generic mixin for managing keyed instancesSingleton: Type-based instance registryIValueForRegistry: Interface for registry-managed objectsSocketType: Enumeration for IPv4/IPv6 socket types
Platform Support #
| Platform | Support | Notes |
|---|---|---|
| Dart CLI | ✅ | Full support |
| Flutter iOS | ✅ | Full support |
| Flutter Android | ✅ | Full support |
| Web | ✅ | UDP via WebRTC data channels |
| macOS | ✅ | Full support |
| Windows | ✅ | Full support |
| Linux | ✅ | Full support |
Requirements #
- Dart SDK:
>=3.9.4 <4.0.0 - For Flutter: Flutter 3.13.0 or higher
Examples #
Comprehensive examples are available in the example/ directory:
- Basic Peer - Simple peer-to-peer communication
- Instance with Keep-Alive - Long-lived connections with heartbeat
- Socket Singleton with Compression - Global socket management with data compression
- Using Interfaces - Dependency injection and interface-based design
- Registry Management (v1.2.0+) - Advanced instance management with registry patterns
Testing #
Run the test suite:
dart pub get
dart test
License #
This package is licensed under the GNU Lesser General Public License v3 (LGPL-3.0-only).
See the LICENSE file for details.
Contributing #
Contributions are welcome! Please feel free to submit pull requests or open issues on GitHub.
Support #
For issues, questions, or suggestions, please use the GitHub issue tracker.