A header-only C++20 networking library providing cross-platform TCP and UDP multicast communication.
- Cross-platform: Windows and Unix/Linux support
- Header-only: No separate compilation required (Windows requires linking slick_socket.lib)
- Modern C++: C++20 design with CRTP for most components
- Asynchronous: Non-blocking socket operations with timeout handling
- TCP Communication: Client and server implementations
- UDP Multicast: One-to-many communication support
- Logging: Template-based logger interface with console output
The easiest way to use slick_socket is to fetch it directly in your CMakeLists.txt:
include(FetchContent)
# Uncomment the line below to disable static lib build on Windows
# set(BUILD_SLICK_SOCKET_STATIC_LIBS OFF CACHE BOOL "" FORCE)
# Uncomment the line below to disable shared lib build on Windows
# set(BUILD_SLICK_SOCKET_SHARED_LIBS OFF CACHE BOOL "" FORCE)
# Disable slick_socket example, and tests
set(BUILD_SLICK_SOCKET_EXAMPLES OFF CACHE BOOL "" FORCE)
set(BUILD_SLICK_SOCKET_TESTING OFF CACHE BOOL "" FORCE)
FetchContent_Declare(
slick_socket
GIT_REPOSITORY https://github.com/SlickQuant/slick_socket.git
GIT_TAG v1.0.3 # Use the desired version
)
FetchContent_MakeAvailable(slick_socket)
# Link against slick_socket
target_link_libraries(your_target PRIVATE slick_socket)On Windows, you also need to link against ws2_32:
target_link_libraries(your_target PRIVATE slick_socket ws2_32)- C++20 compatible compiler (GCC 11+, Clang 12+, MSVC 2022+)
- CMake 3.25 or higher
-
Configure the build:
cmake -S . -B build -
Build the library:
cmake --build build --config Release
-
Copy to your project:
cp -r build/dist/include/slick /path/to/your/project/include/
The library is header-only on Unix/Linux/macOS platforms, so only headers are needed.
-
Configure the build:
cmake -S . -B build -G "Visual Studio 17 2022"
-
Build the library:
cmake --build build --config Release
-
Copy headers and library:
xcopy build\dist\include\slick <your-project>\include\slick /E xcopy build\dist\lib\slick_socket.lib <your-project>\lib\
-
Link in your CMakeLists.txt:
# Add the slick_socket include and lib directories target_include_directories(your_target PRIVATE path/to/slick/include) target_link_directories(your_target PRIVATE path/to/slick/lib) # Link the libraries target_link_libraries(your_target PRIVATE slick_socket ws2_32)
Or manually in Visual Studio:
- Add include path:
path/to/slick/include - Add library path:
path/to/slick/lib - Link with:
slick_socket.libandws2_32.lib
- Add include path:
Include the headers you need in your project:
#include <slick/socket/tcp_server.h>
#include <slick/socket/tcp_client.h>
#include <slick/socket/multicast_sender.h>
#include <slick/socket/multicast_receiver.h>#include <slick/socket/tcp_server.h>
class MyServer : public slick::socket::TCPServerBase<MyServer>
{
public:
MyServer() : TCPServerBase("MyServer", {/*.port = 5000*/}) {}
void onClientConnected(int client_id, const std::string& address)
{
std::cout << "Client " << client_id << " connected from " << address << std::endl;
}
void onClientData(int client_id, const uint8_t* data, size_t size)
{
// Echo back to client
send_data(client_id, std::vector<uint8_t>(data, data + size));
}
void onClientDisconnected(int client_id)
{
std::cout << "Client " << client_id << " disconnected" << std::endl;
}
};
int main()
{
MyServer server;
server.start();
// ... server runs in background thread
return 0;
}#include <slick/socket/tcp_client.h>
class MyClient : public slick::socket::TCPClientBase<MyClient>
{
public:
MyClient(const slick::socket::TCPClientConfig& config)
: TCPClientBase("MyClient", config) {}
void onConnected()
{
std::cout << "Connected to server" << std::endl;
}
void onDisconnected()
{
std::cout << "Disconnected from server" << std::endl;
}
void onData(const uint8_t* data, size_t length)
{
std::string received_data((const char*)data, length);
std::cout << "Received: " << received_data << std::endl;
}
};
int main()
{
slick::socket::TCPClientConfig config;
config.server_address = "127.0.0.1";
config.server_port = 5000;
MyClient client(config);
client.connect();
if (client.is_connected())
{
client.send_data("Hello Server!");
// ... process responses
client.disconnect();
}
return 0;
}#include <slick/socket/multicast_sender.h>
int main()
{
slick::socket::MulticastSenderConfig config;
config.multicast_address = "224.0.0.100";
config.port = 12345;
config.ttl = 1; // Local network only
slick::socket::MulticastSender sender("MySender", config);
if (!sender.start())
{
std::cerr << "Failed to start sender" << std::endl;
return -1;
}
// Send data to multicast group
sender.send_data("Hello Multicast World!");
// Check statistics
std::cout << "Packets sent: " << sender.get_packets_sent() << std::endl;
sender.stop();
return 0;
}#include <slick/socket/multicast_receiver.h>
class MyReceiver : public slick::socket::MulticastReceiverBase<MyReceiver>
{
public:
MyReceiver(const slick::socket::MulticastReceiverConfig& config)
: MulticastReceiverBase("MyReceiver", config) {}
void handle_multicast_data(const std::vector<uint8_t>& data, const std::string& sender_address)
{
std::string message(data.begin(), data.end());
std::cout << "Received from " << sender_address << ": " << message << std::endl;
}
};
int main()
{
slick::socket::MulticastReceiverConfig config;
config.multicast_address = "224.0.0.100";
config.port = 12345;
config.reuse_address = true; // Allow multiple receivers
MyReceiver receiver(config);
if (!receiver.start())
{
std::cerr << "Failed to start receiver" << std::endl;
return -1;
}
// ... receiver runs in background thread
std::this_thread::sleep_for(std::chrono::seconds(30));
receiver.stop();
return 0;
}For more examples, see the examples/ directory.
Run the complete test suite:
cd build && ctest --output-on-failure -C DebugRun specific tests:
cd build && ctest -R TCPServerTest -C DebugEnable verbose test output:
cd build && ctest -V -C DebugEnable AddressSanitizer for debugging memory issues:
cmake -S . -B build -DENABLE_ASAN=ON
cmake --build build --config Debugcmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Releaseslick_socket/
├── include/slick/socket/ # Public headers
│ ├── tcp_server.h # TCP server base class
│ ├── tcp_client.h # TCP client base class
│ ├── multicast_sender.h # UDP multicast sender
│ ├── multicast_receiver.h # UDP multicast receiver
│ └── logger.h # Logger interface
├── src/ # Implementation files (Windows-specific)
├── examples/ # Usage examples
├── tests/ # Unit and integration tests
└── CMakeLists.txt
The library uses a three-file pattern for cross-platform support:
component.h- Base class with platform-independent interfacecomponent_win32.h- Windows implementationcomponent_unix.h- Unix/Linux implementation
Most components use CRTP (Curiously Recurring Template Pattern) for compile-time polymorphism without virtual function overhead. MulticastSender is implemented as a regular class without CRTP for simpler usage.
This project is licensed under the MIT License - see the LICENSE file for details.
Made with ⚡ by SlickQuant