Sane C++ Libraries
C++ Platform Abstraction Libraries
Socket

🟨 Synchronous socket networking and DNS lookup

Socket library allows creating TCP / UDP sockets and using them as client or server and resolving DNS.

It can be used standalone if synchronous networking is preferred or as a companion to Async for creation of non-blocking socket descriptors.

Features

Class Description
SC::SocketServer Use a SocketDescriptor as a Server (example TCP Socket Server).
SC::SocketClient Use a SocketDescriptor as a client (example TCP Socket Client).
SC::SocketIPAddress Native representation of an IP Address.
SC::SocketNetworking DNS Resolution and globals initialization (Winsock2 WSAStartup)

Status

🟨 MVP
Simple synchronous TCP client / server workflow is supported, but it would need better testing.

Description

SC::SocketServer can SC::SocketServer::listen on a given port / address and SC::SocketServer::accept a new client socket. SC::SocketClient can SC::SocketClient::connect, SC::SocketClient::write, SC::SocketClient::read and SC::SocketClient::readWithTimeout.

SC::SocketIPAddress allows creating an ip address native object from a SC::StringView and port.

SC::SocketNetworking class allow resolving a StringView to an IP address.

SocketServer

Example:

SocketDescriptor serverSocket;
SocketServer server(serverSocket);
// Look for an available port
constexpr int tcpPort = 5050;
const StringView serverAddress = "::1"; // or "127.0.0.1"
SocketIPAddress nativeAddress;
SC_TRY(nativeAddress.fromAddressPort(serverAddress, tcpPort));
// Create socket and start listening
SC_TRY(serverSocket.create(nativeAddress.getAddressFamily()));
SC_TRY(server.listen(nativeAddress, tcpPort));
// Accept a client
SocketDescriptor acceptedClientSocket;
SC_TRY(server.accept(family, acceptedClientSocket));
SC_TRY(acceptedClientSocket.isValid());
// ... Do something with acceptedClientSocket
#define SC_TRY(expression)
Checks the value of the given expression and if failed, returns this value to caller.
Definition: Result.h:47

SocketClient

The socket client can be obtained via SC::SocketServer::accept or connected to an endpoint through SC::SocketClient::connect Example (accepted client from server, doing a synchronous read):

SocketDescriptor acceptedClientSocket;
// ... assuming acceptedClientSocket has been obtained with SocketServer::accept
SC_TRY(server.accept(family, acceptedClientSocket));
SC_TRY(acceptedClientSocket.isValid());
// Read some data blocking until it's available
SocketClient acceptedClient(acceptedClientSocket);
Span<char> readData;
SC_TRY(acceptedClient.read({buf, sizeof(buf)}, readData));
SC_TRY(buf[0] == testValue and testValue != 0);
// Read again blocking but with a timeout of 10 seconds
SC_TRY(acceptedClient.readWithTimeout({buf, sizeof(buf)}, readData, 10000_ms));
SC_TRY(buf[0] == testValue + 1);
// Close the client
SC_TRY(acceptedClient.close());

Example (connecting client to server, doing two synchronous writes):

SocketDescriptor clientSocket;
SocketClient client(clientSocket);
// Connect to the server
SC_TRY(client.connect(serverAddress, tcpPort));
// Write some data to the socket
char buf[1] = {testValue};
SC_TRY(client.write({buf, sizeof(buf)}));
buf[0]++; // change the value and write again
SC_TRY(client.write({buf, sizeof(buf)}));
// Close the socket
SC_TRY(client.close());

SocketIPAddress

Example:

SocketIPAddress address;
SC_TEST_EXPECT(not address.fromAddressPort("1223.22.44.1", 6666));
SC_TEST_EXPECT(address.fromAddressPort("127.0.0.1", 123));
SC_TEST_EXPECT(address.fromAddressPort("::1", 123));
#define SC_TEST_EXPECT(e)
Records a test expectation (eventually aborting or breaking o n failed test)
Definition: Testing.h:113

SocketNetworking::resolveDNS

Parameters
[in]hostThe host string (example.com)
[out]ipAddressThe ip address of the given host string
Returns
Valid Result if ip address for the passed host has been successfully resolved

Example:

SmallString<256> ipAddress;
SC_TEST_EXPECT(SocketNetworking::resolveDNS("localhost", ipAddress));
SC_TEST_EXPECT(ipAddress.view() == "127.0.0.1");

Roadmap

🟩 Usable

  • UDP Sockets

🟦 Complete Features:

  • To be decided

💡 Unplanned Features:

  • None so far