jsocketpp 1.0
A cross-platform C++20 socket library.
Loading...
Searching...
No Matches

Low-level socket configuration options exposed via the Socket and related classes. More...

Collaboration diagram for Socket Options:

Classes

class  jsocketpp::SocketOptions
 Public base class for raw socket option access via setsockopt() and getsockopt(). More...

Functions

int jsocketpp::MulticastSocket::getTimeToLive () const
 Get the current default multicast TTL / hop limit cached on this socket.
bool jsocketpp::MulticastSocket::getLoopbackMode () const
 Get the current multicast loopback mode cached on this socket.
void jsocketpp::ServerSocket::setSoTimeout (const int timeoutMillis)
 Set the logical timeout (in milliseconds) for accepting client connections.
int jsocketpp::ServerSocket::getSoTimeout () const noexcept
 Get the logical timeout (in milliseconds) for accept operations.
bool jsocketpp::ServerSocket::isPassiveSocket () const noexcept override
 Identifies this socket as a passive (listening) socket.
 jsocketpp::SocketOptions::SocketOptions ()=delete
 Default constructor (deleted) for SocketOptions base class.
 jsocketpp::SocketOptions::SocketOptions (const SOCKET sock) noexcept
 Initializes the socket option interface with a specific socket descriptor.
virtual jsocketpp::SocketOptions::~SocketOptions ()=default
 Virtual destructor for safe polymorphic destruction.
 jsocketpp::SocketOptions::SocketOptions (const SocketOptions &)=delete
 Copy constructor (deleted) for SocketOptions.
 jsocketpp::SocketOptions::SocketOptions (SocketOptions &&) noexcept=default
 Move constructor for SocketOptions.
SocketOptionsjsocketpp::SocketOptions::operator= (const SocketOptions &)=delete
 Copy assignment operator (deleted) for SocketOptions.
SocketOptionsjsocketpp::SocketOptions::operator= (SocketOptions &&) noexcept=default
 Move assignment operator for SocketOptions.
SOCKET jsocketpp::SocketOptions::getSocketFd () const noexcept
 Retrieves the native socket handle (file descriptor or OS-level handle).
void jsocketpp::SocketOptions::setOption (int level, int optName, int value)
 Sets a low-level socket option on the underlying socket.
void jsocketpp::SocketOptions::setOption (int level, int optName, const void *value, socklen_t len)
 Sets a low-level socket option using a structured or binary value.
int jsocketpp::SocketOptions::getOption (int level, int optName) const
 Retrieves the current value of a low-level socket option.
void jsocketpp::SocketOptions::getOption (int level, int optName, void *result, socklen_t *len) const
 Retrieves a socket option into a structured or binary buffer.
void jsocketpp::SocketOptions::setReuseAddress (bool on)
 Enables or disables the SO_REUSEADDR socket option.
bool jsocketpp::SocketOptions::getReuseAddress () const
 Queries whether the socket is currently configured to allow address reuse.
void jsocketpp::SocketOptions::setReceiveBufferSize (std::size_t size)
 Sets the socket's receive buffer size (SO_RCVBUF).
int jsocketpp::SocketOptions::getReceiveBufferSize () const
 Retrieves the current receive buffer size (SO_RCVBUF) of the socket.
void jsocketpp::SocketOptions::setSendBufferSize (std::size_t size)
 Sets the socket's send buffer size (SO_SNDBUF).
int jsocketpp::SocketOptions::getSendBufferSize () const
 Retrieves the current send buffer size (SO_SNDBUF) of the socket.
void jsocketpp::SocketOptions::setSoLinger (bool enable, int seconds)
 Configures the socket's linger behavior (SO_LINGER) during close.
std::pair< bool, int > jsocketpp::SocketOptions::getSoLinger () const
 Retrieves the current SO_LINGER configuration of the socket.
void jsocketpp::SocketOptions::setKeepAlive (bool on)
 Enables or disables TCP-level keepalive behavior on the socket (SO_KEEPALIVE).
bool jsocketpp::SocketOptions::getKeepAlive () const
 Checks whether TCP-level keepalive (SO_KEEPALIVE) is currently enabled.
void jsocketpp::SocketOptions::setSoRecvTimeout (int millis)
 Sets the socket receive timeout (SO_RCVTIMEO) in milliseconds.
void jsocketpp::SocketOptions::setSoSendTimeout (int millis)
 Sets the socket send timeout (SO_SNDTIMEO) in milliseconds.
int jsocketpp::SocketOptions::getSoRecvTimeout () const
 Retrieves the socket receive timeout (SO_RCVTIMEO) in milliseconds.
int jsocketpp::SocketOptions::getSoSendTimeout () const
 Retrieves the socket send timeout (SO_SNDTIMEO) in milliseconds.
void jsocketpp::SocketOptions::setNonBlocking (bool nonBlocking)
 Enables or disables non-blocking mode on the socket.
bool jsocketpp::SocketOptions::getNonBlocking () const
 Queries whether the socket is currently in non-blocking mode.
void jsocketpp::SocketOptions::setTcpNoDelay (bool on)
 Enables or disables Nagle’s algorithm (TCP_NODELAY) on TCP sockets.
bool jsocketpp::SocketOptions::getTcpNoDelay () const
 Queries whether Nagle's algorithm (TCP_NODELAY) is currently disabled.
void jsocketpp::SocketOptions::setBroadcast (bool on)
 Enables or disables the ability to send UDP broadcast messages.
bool jsocketpp::SocketOptions::getBroadcast () const
 Checks whether the socket is currently allowed to send broadcast messages.
void jsocketpp::SocketOptions::setIPv6Only (bool enable)
 Enables or disables IPV6_V6ONLY mode for IPv6-capable sockets.
bool jsocketpp::SocketOptions::getIPv6Only () const
 Queries whether the IPV6_V6ONLY option is enabled on this socket.
void jsocketpp::SocketOptions::setReusePort (const bool enable)
 Enables or disables the SO_REUSEPORT socket option.
bool jsocketpp::SocketOptions::getReusePort () const
 Checks whether the SO_REUSEPORT option is currently enabled on the socket.
void jsocketpp::SocketOptions::setMulticastTTL (int ttl)
 Set the default multicast hop limit / TTL for this socket.
int jsocketpp::SocketOptions::getMulticastTTL () const
 Get the socket’s default multicast hop limit / TTL.
void jsocketpp::SocketOptions::setMulticastLoopback (bool enable)
 Enable or disable multicast loopback for this socket.
bool jsocketpp::SocketOptions::getMulticastLoopback () const
 Read the socket’s multicast loopback flag.
void jsocketpp::SocketOptions::setMulticastInterfaceIPv4 (in_addr addr)
 Select the outgoing IPv4 interface for multicast.
void jsocketpp::SocketOptions::setMulticastInterfaceIPv6 (unsigned int ifindex)
 Select the outgoing IPv6 interface for multicast.
void jsocketpp::SocketOptions::joinGroupIPv4 (in_addr group, in_addr iface)
 Join an IPv4 any-source multicast (ASM) group on a specific interface.
void jsocketpp::SocketOptions::leaveGroupIPv4 (in_addr group, in_addr iface)
 Leave a previously joined IPv4 multicast group on a specific interface.
void jsocketpp::SocketOptions::joinGroupIPv6 (in6_addr group, unsigned int ifindex)
 Join an IPv6 any-source multicast (ASM) group on a specific interface index.
void jsocketpp::SocketOptions::leaveGroupIPv6 (in6_addr group, unsigned int ifindex)
 Leave a previously joined IPv6 multicast group on a specific interface index.
void jsocketpp::SocketOptions::setSocketFd (const SOCKET sock) noexcept
 Updates the socket descriptor used by this object.
virtual bool jsocketpp::SocketOptions::isPassiveSocket () const noexcept
 Indicates whether the socket behaves as a passive (listening) socket.
static bool jsocketpp::SocketOptions::is_ipv4_multicast (const in_addr v4)
 Test whether an IPv4 address is in the multicast range (224.0.0.0/4).
static bool jsocketpp::SocketOptions::is_ipv6_multicast (const in6_addr &v6)
 Test whether an IPv6 address is in the multicast range (ff00::/8).
static int jsocketpp::SocketOptions::detectFamily (SOCKET fd)
 Determine the address family (AF_INET or AF_INET6) of a socket.

Detailed Description

Low-level socket configuration options exposed via the Socket and related classes.

This module contains functions and accessors for configuring standard socket options such as SO_LINGER, SO_RCVTIMEO, TCP_NODELAY, SO_REUSEADDR, and SO_KEEPALIVE.

These options provide fine-grained control over low-level socket behavior such as timeout behavior, connection shutdown semantics, buffering, and performance tuning.

All functions in this group are cross-platform abstractions over setsockopt() and getsockopt().

Note
Some options may not be available or meaningful on all platforms. Platform-specific behavior is documented per function.
See also
Socket::setSoLinger(), Socket::getSoLinger(), Socket::setTcpNoDelay(), etc.

Function Documentation

◆ detectFamily()

int jsocketpp::SocketOptions::detectFamily ( SOCKET fd)
staticnodiscardprotected

Determine the address family (AF_INET or AF_INET6) of a socket.

Returns the protocol family with which fd was created. On platforms that support it, this first attempts getsockopt(SOL_SOCKET, SO_DOMAIN, ...) and falls back to getsockname() for broad compatibility.

The result is used to pick the correct per-family options for subsequent operations (e.g., IP_MULTICAST_TTL vs IPV6_MULTICAST_HOPS, IP_MULTICAST_LOOP vs IPV6_MULTICAST_LOOP, IP_MULTICAST_IF vs IPV6_MULTICAST_IF, and IPv4/IPv6 group membership APIs).

Parameters
[in]fdThe socket handle to inspect. Must be a valid datagram or stream socket.
Returns
AF_INET for IPv4 sockets or AF_INET6 for IPv6 sockets.
Precondition
  • fd is a valid, open socket descriptor/handle.
Postcondition
  • No socket state is modified. This is a read-only query.
Exceptions
SocketException
  • If fd is invalid (INVALID_SOCKET on Windows or negative on POSIX).
  • If the underlying getsockopt(SO_DOMAIN) or getsockname() call fails; the exception carries the OS error code and message from SocketErrorMessage(...).
  • If the determined family is neither AF_INET nor AF_INET6 (e.g., AF_UNSPEC).
Note
  • On dual-stack sockets (created as AF_INET6 with IPV6_V6ONLY disabled), this function returns AF_INET6. Whether IPv4 behavior is also available is governed by the IPV6_V6ONLY option and OS capabilities.
  • SO_DOMAIN is not universally available; the implementation transparently falls back to getsockname() where necessary.
Related
// Example: choose the correct loopback optname by family
const int fam = detectFamily(sockFd);
const int level = (fam == AF_INET6) ? IPPROTO_IPV6 : IPPROTO_IP;
const int optname = (fam == AF_INET6) ? IPV6_MULTICAST_LOOP : IP_MULTICAST_LOOP;
int on = 1;
setsockopt(sockFd, level, optname, reinterpret_cast<const char*>(&on), sizeof(on));
static int detectFamily(SOCKET fd)
Determine the address family (AF_INET or AF_INET6) of a socket.
Definition SocketOptions.cpp:340

◆ getBroadcast()

bool jsocketpp::SocketOptions::getBroadcast ( ) const
nodiscard

Checks whether the socket is currently allowed to send broadcast messages.

This method retrieves the SO_BROADCAST option using getsockopt() to determine whether the socket can send datagrams to broadcast addresses like 255.255.255.255.


Applicability


Example

if (datagramSocket.getBroadcast()) {
std::cout << "Broadcast is enabled.\n";
} else {
std::cout << "Broadcast is disabled.\n";
}

Returns
true if broadcast mode is enabled, false otherwise.
Exceptions
SocketExceptionif:
  • The socket is invalid
  • The system call fails (getsockopt() error)
  • The socket type is incompatible with this option
See also
setBroadcast()
https://man7.org/linux/man-pages/man7/socket.7.html

◆ getIPv6Only()

bool jsocketpp::SocketOptions::getIPv6Only ( ) const
nodiscard

Queries whether the IPV6_V6ONLY option is enabled on this socket.

This method checks whether the socket is currently restricted to IPv6-only traffic, or whether it allows dual-stack operation (accepting both IPv6 and IPv4-mapped addresses).

The IPV6_V6ONLY flag is primarily relevant to sockets using the AF_INET6 address family.


🌍 Applicability by Socket Type

  • ServerSocket: ✅ Affects accept() behavior for IPv6 listeners
  • Socket: ✅ Optional, useful for bound clients or diagnostic purposes
  • DatagramSocket: ✅ Relevant when binding to IPv6 multicast or wildcard addresses
  • UnixSocket: ❌ Not applicable; throws if called

⚠️ Platform Behavior

  • Linux: Defaults to false (dual-stack), but configurable
  • Windows: Defaults to true (IPv6-only), must be explicitly disabled
  • macOS/BSD: May disallow toggling at runtime or enforce true

Example: Check if socket is IPv6-only

if (socket.getIPv6Only()) {
std::cout << "This socket is IPv6-only.\n";
} else {
std::cout << "Dual-stack mode is active.\n";
}

Returns
true if IPV6_V6ONLY is enabled (IPv6-only mode), false if dual-stack is allowed.
Exceptions
SocketExceptionif:
  • The socket is invalid or closed
  • The system call fails (getsockopt() error)
  • The socket is not an IPv6 socket (i.e., AF_INET6)
Note
Always check that the socket is using the AF_INET6 family before interpreting this flag. Calling this method on a non-IPv6 socket will throw.
See also
setIPv6Only()
https://man7.org/linux/man-pages/man7/ipv6.7.html

◆ getKeepAlive()

bool jsocketpp::SocketOptions::getKeepAlive ( ) const
nodiscard

Checks whether TCP-level keepalive (SO_KEEPALIVE) is currently enabled.

This method queries the socket's current SO_KEEPALIVE setting, which determines whether the operating system sends periodic keepalive probes to verify that idle, stream-oriented connections are still alive.

Keepalive is especially useful for detecting silent disconnects in long-lived connections (e.g., crash, power loss, cable pull) where no TCP FIN/RST is received.

🔁 Applicability

  • TCP sockets (Socket): Fully supported. Returns the current setting.
  • UNIX domain stream sockets (UnixSocket): Supported on most POSIX platforms.
  • Accepted sockets in ServerSocket: Each accepted socket can be queried individually.
  • ⚠️ UDP / datagram sockets (DatagramSocket): Most systems ignore this option; querying may return false or raise an error depending on platform behavior.

Platform Behavior

  • Linux/macOS/BSD: Returns true if SO_KEEPALIVE is enabled at the socket level. Probe intervals and behavior are system-controlled unless overridden via additional options.
  • Windows: Returns true if enabled. Advanced tuning requires use of WSAIoctl.

Example

if (!socket.getKeepAlive()) {
socket.setKeepAlive(true);
std::cout << "Keepalive enabled.\n";
}
Returns
true if keepalive is enabled; false if disabled.
Exceptions
SocketExceptionif:
  • The socket is invalid or closed
  • getsockopt() fails
  • The platform does not support the option on this socket type
See also
setKeepAlive()
setOption()
https://man7.org/linux/man-pages/man7/tcp.7.html
Note
This method only checks whether SO_KEEPALIVE is enabled. It does not report the configured keepalive timing parameters (interval, probes, idle time), which are system-defined.

◆ getLoopbackMode()

bool jsocketpp::MulticastSocket::getLoopbackMode ( ) const
inlinenodiscard

Get the current multicast loopback mode cached on this socket.

Reports whether this object is configured to receive local copies of its own multicast transmissions (“loopback”). The value reflects the last successful call to setLoopbackMode(bool) made through this class; it does not perform a fresh kernel query.

Semantics of the returned flag:

  • true — loopback enabled; if this socket has joined the destination group, the kernel may deliver local copies of this socket’s outbound multicast.
  • false — loopback disabled; local delivery of this socket’s outbound multicast is suppressed on the host.

This accessor concerns multicast only; it does not affect nor report unicast behavior.

Returns
true if multicast loopback is enabled according to this object’s cached state; otherwise false.
Precondition
  • None. This is a read-only accessor.
Postcondition
  • No side effects; neither socket nor object state is modified.
Note
  • The value is cached in this class (e.g., _loopbackEnabled). If other code changes the OS-level setting directly (e.g., via setMulticastLoopback(bool) on the underlying options object), this cached flag may not reflect the kernel’s current configuration. Use getMulticastLoopback() to perform a fresh OS query.
  • To actually receive your own transmissions on this socket, two conditions must hold: (1) loopback is enabled, and (2) the socket has joined the destination group.
Related options
// Ensure we will receive our own announcements on this host:
if (!sock.getLoopbackMode()) {
sock.setLoopbackMode(true);
}

◆ getMulticastLoopback()

bool jsocketpp::SocketOptions::getMulticastLoopback ( ) const
nodiscard

Read the socket’s multicast loopback flag.

Queries whether multicast datagrams transmitted by this socket are eligible for local delivery back to the host (“loopback”).

  • IPv4: reads IP_MULTICAST_LOOP.
  • IPv6: reads IPV6_MULTICAST_LOOP.

Semantics of the returned flag:

  • true — the kernel may deliver local copies of this socket’s outbound multicast to sockets on the same host that have joined the destination group (including this socket if it has joined).
  • false — the kernel suppresses local delivery of this socket’s outbound multicast.

This is a read-only query of the per-socket default and does not affect unicast traffic, nor does it consider any per-message control data. It reports the socket’s current loopback policy only.

Returns
true if multicast loopback is enabled for this socket; otherwise false.
Precondition
  • The underlying descriptor is a valid socket of family AF_INET or AF_INET6.
Postcondition
  • Socket state is unchanged; this call performs no modifications.
Platform mapping
  • IPv4: getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, ...)
  • IPv6: getsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, ...)
Error conditions
  • The socket is invalid or closed.
  • The socket family cannot be determined or is unsupported on this platform.
  • The underlying getsockopt call fails (e.g., ENOTSOCK, ENOPROTOOPT, EINVAL, or Windows equivalents WSAENOTSOCK, WSAENOPROTOOPT, WSAEINVAL).
Exceptions
SocketExceptionIf the query fails for any of the reasons above. The exception carries the OS error code and a descriptive message produced by SocketErrorMessage(...).
Note
  • Typical default is enabled on many stacks, but this is implementation-defined; applications that rely on a specific policy should call setMulticastLoopback(bool) during initialization.
  • Loopback controls local delivery only. Remote receivers are unaffected.
  • To receive your own transmissions on this socket, both conditions must hold: (1) loopback is enabled, and (2) the socket has joined the destination group.
  • Concurrent calls to setMulticastLoopback(bool) may race with this query; the value returned is a snapshot at the time of the call.
Related options
// Example: ensure loopback is enabled so we can observe our own group traffic
if (!sock.getMulticastLoopback()) {
sock.setMulticastLoopback(true);
}
// Now, if this socket has joined the group, it can receive its own sends.

◆ getMulticastTTL()

int jsocketpp::SocketOptions::getMulticastTTL ( ) const
nodiscard

Get the socket’s default multicast hop limit / TTL.

Returns the current per-socket default scope used for outbound multicast transmissions:

  • For IPv4 sockets, this queries IP_MULTICAST_TTL (time-to-live).
  • For IPv6 sockets, this queries IPV6_MULTICAST_HOPS (hop limit).

The returned value determines how far multicast packets sent from this socket may propagate by default:

  • 0 confines delivery to the local host.
  • 1 confines delivery to the local link / subnet.
  • Larger values permit traversal across additional multicast routers, up to the limit.

This query does not affect unicast traffic—use IP_TTL / IPV6_UNICAST_HOPS for unicast scope—and does not consider any per-message overrides supplied via ancillary data (e.g., IP_MULTICAST_TTL / IPV6_HOPLIMIT control messages). It reports the socket’s default only.

Returns
TTL / hop-limit in the range [0, 255] currently configured on this socket for multicast transmissions.
Precondition
  • The underlying descriptor is a valid socket of family AF_INET or AF_INET6.
Postcondition
  • Socket state is unchanged; this is a read-only query.
Platform mapping
  • IPv4: getsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, ...)
  • IPv6: getsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ...)
Error conditions
  • The socket is invalid or closed.
  • The socket family cannot be determined or is unsupported.
  • The underlying getsockopt call fails (e.g., ENOTSOCK, ENOPROTOOPT, EINVAL, or Windows equivalents such as WSAENOTSOCK, WSAENOPROTOOPT, WSAEINVAL).
Exceptions
SocketExceptionIf the query fails for any of the reasons above. The exception carries the OS error code and a descriptive message produced by SocketErrorMessage(...).
Note
  • The initial value is implementation-defined (commonly 1); applications that require a specific scope should call setMulticastTTL(int) during initialization.
  • Concurrent calls to setMulticastTTL(int) may race with this query; the value returned is a snapshot at the time of the call.
Related options
// Example: read current default, ensure at least link-local reach (>= 1)
[[maybe_unused]] auto current = sock.getMulticastTTL();
if (current < 1) {
sock.setMulticastTTL(1);
}

◆ getNonBlocking()

bool jsocketpp::SocketOptions::getNonBlocking ( ) const
nodiscard

Queries whether the socket is currently in non-blocking mode.

This method inspects the I/O mode of the socket and returns true if it is configured for non-blocking operations. In non-blocking mode, I/O system calls return immediately if they cannot complete, rather than blocking the calling thread.


🔀 Platform Behavior

  • POSIX: Checks the O_NONBLOCK flag using fcntl(F_GETFL).
  • Windows: No direct API exists to query non-blocking state. This function will conservatively return false and emit a warning if queried.

Use Cases

  • Debugging or inspecting socket configuration
  • Adaptive I/O logic based on runtime state

Example

if (!socket.getNonBlocking()) {
socket.setNonBlocking(true);
}

Returns
true if the socket is in non-blocking mode, false otherwise. On Windows, always returns false due to lack of system support.
Exceptions
SocketExceptionif:
  • The socket is invalid
  • The system query fails (e.g., fcntl returns error on POSIX)
Note
On Windows, there is no way to detect the current non-blocking state via public APIs. You must track it manually in application logic if needed.
See also
setNonBlocking()

◆ getOption() [1/2]

int jsocketpp::SocketOptions::getOption ( int level,
int optName ) const
nodiscard

Retrieves the current value of a low-level socket option.

This method queries a socket option using the system-level getsockopt() interface. It returns the current value as an integer and is useful for inspecting platform defaults, runtime configuration, or verifying changes made via setOption().

This method is supported by all socket types provided by the library:

It supports standard protocol levels such as SOL_SOCKET, IPPROTO_TCP, and IPPROTO_UDP.


🔧 Use Cases

  • Verify receive/send buffer sizes (SO_RCVBUF, SO_SNDBUF)
  • Check if keepalive or broadcast is enabled (SO_KEEPALIVE, SO_BROADCAST)
  • Inspect linger state (SO_LINGER) via the structured overload

Example: Read configured receive buffer size

int rcvBuf = socket.getOption(SOL_SOCKET, SO_RCVBUF);

⚠️ ServerSocket-specific Notes

  • Applies only to the listening socket.
  • Use this to inspect pre-accept behavior such as:
    • SO_REUSEADDR, SO_LINGER, SO_RCVBUF, etc.
  • Accepted client sockets must be queried individually.
int reuse = serverSocket.getOption(SOL_SOCKET, SO_REUSEADDR);

📡 DatagramSocket-specific Notes

  • Useful for checking SO_BROADCAST, SO_RCVTIMEO, SO_SNDTIMEO, and buffer sizes.
  • Behavior is consistent across connected and unconnected UDP sockets.
int timeout = datagramSocket.getOption(SOL_SOCKET, SO_RCVTIMEO);

🧿 UnixSocket-specific Notes

  • SO_RCVBUF, SO_SNDBUF, SO_PASSCRED, and timeout options are supported.
  • Can be used for IPC performance diagnostics.
int bufSize = unixSocket.getOption(SOL_SOCKET, SO_SNDBUF);

Parameters
[in]levelProtocol level (e.g., SOL_SOCKET, IPPROTO_TCP)
[in]optNameSocket option name (e.g., SO_KEEPALIVE, SO_SNDBUF)
Returns
Integer value of the requested option
Exceptions
SocketExceptionif:
  • The socket is invalid
  • The option is unsupported or improperly configured
  • The getsockopt() call fails
See also
setOption(int, int, int)
getOption(int, int, void*, socklen_t*) For retrieving structured options
https://man7.org/linux/man-pages/man2/getsockopt.2.html

◆ getOption() [2/2]

void jsocketpp::SocketOptions::getOption ( int level,
int optName,
void * result,
socklen_t * len ) const

Retrieves a socket option into a structured or binary buffer.

This overload of getOption() allows querying complex or platform-specific socket options that require structured output (e.g., struct linger, struct timeval, etc.). It wraps the system-level getsockopt() call using a raw memory buffer and returns the result through the provided pointer.

The semantics are identical to the getOption(int, int) overload, but this version is used for retrieving non-integer options.

This method works uniformly across:


🔧 Use Cases

  • Query SO_LINGER using struct linger
  • Read timeout values into struct timeval
  • Inspect platform-specific flags or metadata structures
  • Use with low-level protocol options that return binary data

Example: Read SO_LINGER setting

linger lin{};
socklen_t len = sizeof(lin);
socket.getOption(SOL_SOCKET, SO_LINGER, &lin, &len);
if (lin.l_onoff)
std::cout << "Linger enabled for " << lin.l_linger << " seconds.\n";
else
std::cout << "Linger is disabled.\n";

⚠️ ServerSocket-specific Notes

  • Applies to the listening socket only (not accepted clients).
  • Common for querying SO_LINGER, SO_RCVBUF, etc.

📡 DatagramSocket-specific Notes

  • Use to inspect structured timeouts (SO_RCVTIMEO) or multicast settings.
  • Valid on both connected and unconnected sockets.

🧿 UnixSocket-specific Notes

  • Retrieve SO_PASSCRED, buffer sizes, and timeouts using appropriate structures.
  • Useful for debugging IPC characteristics and system resource tuning.

Parameters
[in]levelProtocol level (e.g., SOL_SOCKET, IPPROTO_TCP)
[in]optNameSocket option name (e.g., SO_LINGER)
[out]resultPointer to a buffer to receive the option value
[out]lenPointer to the size of the buffer. On return, holds the actual size used.
Exceptions
SocketExceptionif:
  • The socket is invalid or closed
  • result or len is null
  • The option is unsupported or the system call fails
Note
The caller is responsible for allocating and sizing the buffer. The len parameter must be set to the size of the buffer before the call.
See also
getOption(int, int) For integer-based options
setOption(int, int, const void*, socklen_t) For setting structured values
https://man7.org/linux/man-pages/man2/getsockopt.2.html

◆ getReceiveBufferSize()

int jsocketpp::SocketOptions::getReceiveBufferSize ( ) const
nodiscard

Retrieves the current receive buffer size (SO_RCVBUF) of the socket.

Queries the operating system for the size of the receive buffer allocated to this socket. This buffer temporarily holds incoming data before it is read by the application. The size is determined by system policy, user configuration, and the value set via setReceiveBufferSize().

Applicability

This method works for:

  • TCP sockets (Socket): Indicates how much inbound data can be queued before blocking or drop.
  • UDP sockets (DatagramSocket): Critical for burst tolerance and loss avoidance.
  • UNIX domain sockets: Supported on most platforms.
  • ServerSocket: Reflects configuration of the passive socket itself (not accepted sockets).

Platform Notes

  • Linux: Returned value is typically twice the requested size due to internal accounting.
  • Windows: Rounded to alignment boundaries; value reflects what was granted, not requested.
  • BSD/macOS: Exact behavior may vary, but returned size reflects the OS’s accepted setting.

Example

int size = socket.getReceiveBufferSize();
std::cout << "Current OS receive buffer: " << size << " bytes\n";
Returns
The actual receive buffer size in bytes as allocated by the operating system.
Exceptions
SocketExceptionif:
  • The socket is invalid (e.g., not open or moved-from)
  • The system call fails (e.g., due to low-level error)
  • Permissions are insufficient
Note
To verify that setReceiveBufferSize() took effect, compare the returned value here.
See also
setReceiveBufferSize()
getSendBufferSize()
setInternalBufferSize()

◆ getReuseAddress()

bool jsocketpp::SocketOptions::getReuseAddress ( ) const
nodiscard

Queries whether the socket is currently configured to allow address reuse.

This method retrieves the state of the SO_REUSEADDR socket option using getsockopt(). When enabled, it allows the socket to bind to a local address/port that is already in use or still in the TIME_WAIT state. This is particularly useful in scenarios such as:

  • Restartable TCP servers that must rebind quickly
  • UDP or multicast receivers sharing the same port
  • Clients using fixed local ports across reconnects

Platform Behavior

  • POSIX: Multiple sockets can bind the same local address/port if all use SO_REUSEADDR.
  • Windows: SO_REUSEADDR allows rebinding to a port in TIME_WAIT, but does not allow simultaneous binds. Additionally, SO_EXCLUSIVEADDRUSE is enabled by default and disables reuse — this method reflects the effective state of SO_REUSEADDR, not SO_EXCLUSIVEADDRUSE.

Protocol Applicability

  • TCP: Useful for both client and server sockets.
  • UDP: Required for multicast and shared-port scenarios.
  • Unix domain sockets: SO_REUSEADDR may be supported but is typically a no-op; Unix path conflicts are governed by the file system.

Example

if (!socket.getReuseAddress()) {
socket.setReuseAddress(true);
}
Returns
true if address reuse is currently enabled; false otherwise.
Exceptions
SocketExceptionif the socket is invalid or the option cannot be retrieved.
Note
Always call this after socket creation and before bind() to ensure valid results.
See also
setReuseAddress()
https://man7.org/linux/man-pages/man7/socket.7.html

◆ getReusePort()

bool jsocketpp::SocketOptions::getReusePort ( ) const
nodiscard

Checks whether the SO_REUSEPORT option is currently enabled on the socket.

This method queries the SO_REUSEPORT setting via getsockopt() to determine whether the socket is configured to allow multiple bindings to the same address/port.


🌍 Applicability

  • ServerSocket: ✅ Used to verify shared accept-mode configuration
  • DatagramSocket: ✅ Useful for multicast receivers or redundant UDP listeners
  • Socket: ✅ Rare, but valid for bound client sockets
  • UnixSocket: ❌ Not applicable — method excluded at compile time

🔀 Platform Support

  • Linux (≥ 3.9), FreeBSD, macOS (some BSDs require extra sysctls)
  • Windows: Not supported — this method is not compiled

Example

#if defined(SO_REUSEPORT)
if (socket.getReusePort()) {
std::cout << "Port reuse is enabled.\n";
} else {
std::cout << "Port reuse is not enabled.\n";
}
#endif

Returns
true if SO_REUSEPORT is enabled on the socket; false otherwise.
Exceptions
SocketExceptionif:
  • The socket is invalid or uninitialized
  • The system call fails (getsockopt() error)
  • The option is not supported or the socket type is incompatible
See also
setReusePort()
https://man7.org/linux/man-pages/man7/socket.7.html

◆ getSendBufferSize()

int jsocketpp::SocketOptions::getSendBufferSize ( ) const
nodiscard

Retrieves the current send buffer size (SO_SNDBUF) of the socket.

Queries the operating system for the size of the send buffer allocated to this socket. This buffer holds outgoing data that has been written by the application but not yet transmitted over the network or IPC channel. A larger send buffer allows the socket to tolerate bursts of data or temporary network slowdowns without blocking the writer.

Applicability

This method is supported for:

  • TCP sockets (Socket): Improves write throughput and non-blocking behavior.
  • UDP sockets (DatagramSocket): Enables larger bursts of outgoing datagrams.
  • UNIX domain sockets: Applies to stream or datagram sockets on most platforms.
  • ServerSocket: Returns the buffer size of the passive socket, but has no effect on accepted sockets.

Platform Notes

  • Linux: May return a value twice the requested size due to kernel bookkeeping.
  • Windows: Returns the actual allocated size, rounded internally by Winsock.
  • BSD/macOS: Behavior follows BSD socket semantics.
  • System-wide limits may apply, and the kernel may clamp, align, or ignore extreme values.

Example

int size = socket.getSendBufferSize();
std::cout << "Send buffer size: " << size << " bytes\n";
Returns
Actual send buffer size in bytes, as reported by the kernel.
Exceptions
SocketExceptionif:
  • The socket is invalid or closed
  • The getsockopt() call fails
  • Permissions are insufficient to query socket settings
Note
The value returned may differ from what was passed to setSendBufferSize(). Always query after setting to determine the effective size.
See also
setSendBufferSize()
getReceiveBufferSize()
setReceiveBufferSize()

◆ getSocketFd()

SOCKET jsocketpp::SocketOptions::getSocketFd ( ) const
inlinenodiscardnoexcept

Retrieves the native socket handle (file descriptor or OS-level handle).

This method provides low-level access to the socket’s operating system identifier:

  • On POSIX systems, this is an integer file descriptor (int)
  • On Windows, this is a SOCKET handle (uintptr_t-like)

It is intended for advanced use cases only, such as:

  • Integrating with external event loops (select(), poll(), epoll, kqueue)
  • Passing the socket to platform APIs or native libraries
  • Monitoring socket state or readiness using system primitives

⚠️ HANDLE WITH EXTREME CARE

This method exposes the raw handle without ownership transfer. Misuse may lead to:

  • Resource leaks (if manually closed)
  • Double-close or shutdown
  • Corruption of internal state
  • Thread-safety issues in multithreaded environments
  • Broken invariants inside the jsocketpp abstraction

✅ Safe Usage Guidelines

  • DO use this handle for non-destructive introspection (e.g., poll(), select())
  • DO NOT call close(), shutdown(), or setsockopt() directly unless you fully understand the consequences
  • DO NOT store the handle beyond the lifetime of the socket object
  • DO NOT share across threads without synchronization

Example: Use with select()

fd_set readSet;
FD_ZERO(&readSet);
FD_SET(socket.getSocketFd(), &readSet);
if (::select(socket.getSocketFd() + 1, &readSet, nullptr, nullptr, &timeout) > 0) {
std::cout << "Socket is readable!\n";
}
Returns
The underlying OS-level socket identifier (SOCKET or file descriptor). Returns INVALID_SOCKET if the socket is not initialized.
See also
setSocketFd() – Internal method for synchronizing base state
setOption(), getOption()
waitReady(), setNonBlocking()

◆ getSoLinger()

std::pair< bool, int > jsocketpp::SocketOptions::getSoLinger ( ) const
nodiscard

Retrieves the current SO_LINGER configuration of the socket.

Queries the operating system for the current linger behavior configured on this socket. Linger settings determine whether the socket blocks on close() to allow unsent data to be transmitted, or terminates the connection immediately (potentially discarding unsent data).

🔁 Applicability

  • TCP sockets (Socket): Fully supported; reflects actual linger settings.
  • UNIX domain stream sockets: Supported on most POSIX platforms.
  • ⚠️ UDP / datagram sockets (DatagramSocket): SO_LINGER is silently ignored by most systems.
  • ⚠️ ServerSocket: Applies only to the passive (listening) socket. To inspect accepted clients, query each returned Socket individually.

Return Value

Returns a pair {enabled, timeout}:

  • first (bool): Whether SO_LINGER is currently enabled.
  • second (int): Timeout value in seconds (typically 0 if disabled).

Example

auto [enabled, timeout] = socket.getSoLinger();
if (enabled)
std::cout << "Linger is enabled for " << timeout << " seconds.\n";
else
std::cout << "Linger is disabled.\n";
Exceptions
SocketExceptionif:
  • The socket is invalid
  • The system call fails
  • The option is unsupported or not implemented on the platform
See also
setSoLinger()
shutdown()
close()
Note
On many platforms, this option is only meaningful for stream-oriented sockets. Behavior for datagram sockets is undefined or silently ignored.

◆ getSoRecvTimeout()

int jsocketpp::SocketOptions::getSoRecvTimeout ( ) const
nodiscard

Retrieves the socket receive timeout (SO_RCVTIMEO) in milliseconds.

This method queries the configured timeout for blocking read operations, such as read(), readExact(), receiveFrom(), etc. The value returned represents the number of milliseconds a read will block before failing with a timeout.


🔀 Platform Behavior

  • Windows: Returns the timeout directly as an int in milliseconds.
  • POSIX: Retrieves a struct timeval and converts it to milliseconds.

Example

int timeout = socket.getSoRecvTimeout();
std::cout << "Read timeout is " << timeout << " ms\n";

Returns
The current receive timeout in milliseconds. A value of 0 indicates no timeout (i.e., blocking indefinitely).
Exceptions
SocketExceptionif:
  • The socket is invalid
  • getsockopt() fails
  • The timeout cannot be retrieved due to system-level error
See also
setSoRecvTimeout()
getSoSendTimeout()

◆ getSoSendTimeout()

int jsocketpp::SocketOptions::getSoSendTimeout ( ) const
nodiscard

Retrieves the socket send timeout (SO_SNDTIMEO) in milliseconds.

This method queries the configured timeout for blocking send operations, such as write(), writeAll(), or sendTo(). The returned value represents how long a send operation will block before timing out.


🔀 Platform Behavior

  • Windows: Timeout is retrieved as a plain int (milliseconds).
  • POSIX: The timeout is stored in a struct timeval and converted back.

Example

int timeout = socket.getSoSendTimeout();
std::cout << "Send timeout is " << timeout << " ms\n";

Returns
The current send timeout in milliseconds. A value of 0 indicates no timeout (i.e., blocking indefinitely).
Exceptions
SocketExceptionif:
  • The socket is invalid
  • getsockopt() fails
  • The system reports an unexpected or unsupported configuration
See also
setSoSendTimeout()
getSoRecvTimeout()

◆ getSoTimeout()

int jsocketpp::ServerSocket::getSoTimeout ( ) const
inlinenodiscardnoexcept

Get the logical timeout (in milliseconds) for accept operations.

This value determines how long methods like accept() and tryAccept() will wait for an incoming client connection before timing out. It is used internally by select() or similar readiness mechanisms.

Note
This timeout is a logical userland timeout and does not affect the socket descriptor via setsockopt() (unlike Socket::getSoTimeout()).
Returns
The configured accept timeout in milliseconds.
See also
setSoTimeout()
accept()
tryAccept()

◆ getTcpNoDelay()

bool jsocketpp::SocketOptions::getTcpNoDelay ( ) const
nodiscard

Queries whether Nagle's algorithm (TCP_NODELAY) is currently disabled.

This method checks if TCP_NODELAY is set on the socket, which controls the behavior of Nagle's algorithm for TCP connections. When TCP_NODELAY is enabled (true), small writes are sent immediately without waiting to coalesce packets. When disabled (false), the system may buffer small packets to improve network efficiency.


🔍 Applicability

This option applies only to:

  • TCP stream sockets (SOCK_STREAM with AF_INET or AF_INET6)

It does not apply to:


Use Cases

  • Determine latency behavior at runtime
  • Validate low-latency configuration in unit tests
  • Debug unexpected TCP buffering issues

Example

if (!socket.getTcpNoDelay()) {
socket.setTcpNoDelay(true); // Reduce latency
}

Returns
true if Nagle's algorithm is disabled (TCP_NODELAY = 1), false if Nagle’s algorithm is enabled (TCP_NODELAY = 0)
Exceptions
SocketExceptionif:
  • The socket is invalid or closed
  • The option is not supported on the current socket type
  • A system-level query fails (getsockopt() error)
See also
setTcpNoDelay()
https://en.wikipedia.org/wiki/Nagle%27s_algorithm
https://man7.org/linux/man-pages/man7/tcp.7.html

◆ getTimeToLive()

int jsocketpp::MulticastSocket::getTimeToLive ( ) const
inline

Get the current default multicast TTL / hop limit cached on this socket.

Returns this object’s cached per-socket default scope for outbound multicast transmissions as last set via setTimeToLive(int). It does not perform a fresh kernel query and does not affect any state.

Semantics of the returned value (applies to multicast only):

  • 0 — restricted to the local host (no network egress);
  • 1 — restricted to the local link / subnet (commonly the default);
  • 32 — typically site scope;
  • 64 — typically region scope;
  • 128 — typically continent scope;
  • 255 — unrestricted (global), subject to network policy.
Returns
The cached multicast TTL / hop-limit in the range [0, 255].
Precondition
  • None. This is a read-only accessor.
Postcondition
  • No side effects; socket and object state are unchanged.
Note
  • This accessor reports the value cached by this class (e.g., updated by setTimeToLive(int)). If other code changes the OS-level default directly (e.g., via setMulticastTTL(int) on SocketOptions), this cached value may not reflect the kernel’s current setting.
  • The value applies to multicast only. Unicast scope is controlled by IP_TTL / IPV6_UNICAST_HOPS.
Related options
// Ensure at least link-local reach for multicast
if (sock.getTimeToLive() < 1) {
sock.setTimeToLive(1);
}

◆ is_ipv4_multicast()

bool jsocketpp::SocketOptions::is_ipv4_multicast ( const in_addr v4)
inlinestaticprotected

Test whether an IPv4 address is in the multicast range (224.0.0.0/4).

Lightweight predicate that checks if v4 lies within the IPv4 multicast block 224.0.0.0/4 (i.e., 224.0.0.0–239.255.255.255). Internally uses the standard IN_MULTICAST() macro against the host-order form of the address.

Parameters
[in]v4IPv4 address in a POSIX in_addr struct. Byte order: v4.s_addr must be in network byte order (as produced by inet_pton(AF_INET, ...) or stored in socket APIs). This helper converts to host order before evaluation.
Returns
true if the address is multicast; otherwise false.
Precondition
  • None. The function is total for any in_addr value.
Postcondition
  • No side effects. This function is constexpr-friendly in spirit (not declared constexpr purely due to macro use) and thread-safe.
Byte order
  • IN_MULTICAST() expects a host-order 32-bit address. This helper applies ntohl(v4.s_addr) to ensure correctness regardless of caller endianness.
Implementation notes
  • Equivalent to: return IN_MULTICAST(ntohl(v4.s_addr)) != 0;
  • This check does not validate group semantics beyond the range test (e.g., administratively scoped subranges). Use it as a fast guard before calling join/leave APIs.
Related options
// Example 1: literal parse and check
in_addr g{};
if (inet_pton(AF_INET, "239.1.2.3", &g) != 1)
throw std::runtime_error("invalid IPv4 address");
throw SocketException("Expected an IPv4 multicast address");
// Example 2: reject non-multicast
in_addr u{};
inet_pton(AF_INET, "192.168.1.10", &u);
// unreachable in this example
}
// Example 3: guard before joining a group
in_addr iface{}; iface.s_addr = htonl(INADDR_ANY);
throw SocketException("Not a multicast group");
joinGroupIPv4(g, iface);
Represents socket-related errors in the jsocketpp library.
Definition SocketException.hpp:63
static bool is_ipv4_multicast(const in_addr v4)
Test whether an IPv4 address is in the multicast range (224.0.0.0/4).
Definition SocketOptions.hpp:2370
void joinGroupIPv4(in_addr group, in_addr iface)
Join an IPv4 any-source multicast (ASM) group on a specific interface.
Definition SocketOptions.cpp:470

◆ is_ipv6_multicast()

bool jsocketpp::SocketOptions::is_ipv6_multicast ( const in6_addr & v6)
inlinestaticprotected

Test whether an IPv6 address is in the multicast range (ff00::/8).

Lightweight predicate that checks if v6 lies within the IPv6 multicast prefix ff00::/8. Internally uses the standard IN6_IS_ADDR_MULTICAST() macro.

Parameters
[in]v6IPv6 address in a POSIX in6_addr struct. No byte-order adjustment is required by the caller; the macro reads the struct fields directly.
Returns
true if the address is multicast; otherwise false.
Precondition
  • None. The function is total for any in6_addr value.
Postcondition
  • No side effects; thread-safe.
Scope vs. membership
  • This helper only verifies membership in ff00::/8. It does not report the multicast scope (node, link, site, org, global). If you need scope, consult the standard predicates such as: IN6_IS_ADDR_MC_NODELOCAL, IN6_IS_ADDR_MC_LINKLOCAL, IN6_IS_ADDR_MC_SITELOCAL, etc., depending on your platform.
Implementation notes
  • Equivalent to: return IN6_IS_ADDR_MULTICAST(&v6) != 0;
  • Use as a fast guard prior to join/leave calls for IPv6 groups.
Related options
// Example 1: literal parse and check
in6_addr g6{};
if (inet_pton(AF_INET6, "ff02::1", &g6) != 1)
throw std::runtime_error("invalid IPv6 address");
throw SocketException("Expected an IPv6 multicast address");
// Example 2: reject non-multicast
in6_addr u6{};
inet_pton(AF_INET6, "2001:db8::1", &u6);
// unreachable in this example
}
// Example 3: guard before joining a group (interface index 0 = default)
unsigned int ifindex = 0;
throw SocketException("Not a multicast group");
joinGroupIPv6(g6, ifindex);
static bool is_ipv6_multicast(const in6_addr &v6)
Test whether an IPv6 address is in the multicast range (ff00::/8).
Definition SocketOptions.hpp:2430
void joinGroupIPv6(in6_addr group, unsigned int ifindex)
Join an IPv6 any-source multicast (ASM) group on a specific interface index.
Definition SocketOptions.cpp:500

◆ isPassiveSocket() [1/2]

bool jsocketpp::ServerSocket::isPassiveSocket ( ) const
inlinenodiscardoverrideprotectedvirtualnoexcept

Identifies this socket as a passive (listening) socket.

Overrides the base SocketOptions::isPassiveSocket() to return true, indicating that this ServerSocket instance is intended to accept incoming connections rather than initiate outbound ones.

This designation is important for platform-specific behaviors — particularly on Windows, where passive sockets use SO_EXCLUSIVEADDRUSE instead of SO_REUSEADDR to control address reuse semantics. The SocketOptions interface uses this signal to select the correct option and logic in setReuseAddress() and getReuseAddress().

When true matters

  • Enables use of SO_EXCLUSIVEADDRUSE on Windows
  • Prevents unsafe or misleading reuse logic on listening sockets
  • Helps unify reuse handling logic across all socket types in a central place
Returns
Always returns true for ServerSocket to indicate passive socket behavior.
See also
SocketOptions::isPassiveSocket()
SocketOptions::setReuseAddress()
SocketOptions::getReuseAddress()

Reimplemented from jsocketpp::SocketOptions.

◆ isPassiveSocket() [2/2]

virtual bool jsocketpp::SocketOptions::isPassiveSocket ( ) const
inlinenodiscardprotectedvirtualnoexcept

Indicates whether the socket behaves as a passive (listening) socket.

This virtual method is used internally by the SocketOptions interface to determine whether the socket is operating in a passive role — that is, it is a listening socket typically created by a server to accept incoming connections. This distinction is particularly relevant on platforms like Windows, where different socket options apply to passive vs. active sockets.

Specifically, this affects how address reuse logic is applied:

  • On Windows, SO_EXCLUSIVEADDRUSE is used for passive sockets to control port reuse semantics.
  • On POSIX systems, all sockets use SO_REUSEADDR, but server sockets may still follow different best practices.

Usage

  • Override this method in subclasses like ServerSocket to return true.
  • Leave it as false (default) in client sockets, UDP sockets, or Unix domain sockets.
Returns
true if the socket is used in a listening or acceptor role; false otherwise.
Note
This method has no direct side effects. It exists purely to guide conditional logic in reusable base class operations such as setReuseAddress() and getReuseAddress().
See also
setReuseAddress()
getReuseAddress()
ServerSocket

Reimplemented in jsocketpp::ServerSocket.

◆ joinGroupIPv4()

void jsocketpp::SocketOptions::joinGroupIPv4 ( in_addr group,
in_addr iface )

Join an IPv4 any-source multicast (ASM) group on a specific interface.

Joins group on the IPv4 interface identified by iface. The interface must be specified by its unicast IPv4 address (network order). Use {INADDR_ANY} to let the stack choose a default interface.

Parameters
[in]groupMulticast group address (network order). Must satisfy IN_MULTICAST().
[in]ifaceLocal interface address (network order). Use {INADDR_ANY} for default.
Exceptions
SocketExceptionIf the socket is invalid, group is not multicast, or the underlying setsockopt(IP_ADD_MEMBERSHIP) fails. Error text is produced by SocketErrorMessage(...).

◆ joinGroupIPv6()

void jsocketpp::SocketOptions::joinGroupIPv6 ( in6_addr group,
unsigned int ifindex )

Join an IPv6 any-source multicast (ASM) group on a specific interface index.

Joins group on the interface identified by ifindex. Use 0 for the default interface. group must be a multicast address.

Parameters
[in]groupIPv6 multicast group address.
[in]ifindexIPv6 interface index (0 for default).
Exceptions
SocketExceptionIf the socket is invalid, group is not multicast, or the underlying setsockopt(IPV6_JOIN_GROUP) (POSIX) or IPV6_ADD_MEMBERSHIP (Windows) fails.

◆ leaveGroupIPv4()

void jsocketpp::SocketOptions::leaveGroupIPv4 ( in_addr group,
in_addr iface )

Leave a previously joined IPv4 multicast group on a specific interface.

Parameters
[in]groupMulticast group address (network order).
[in]ifaceInterface address used when joining (network order).
Exceptions
SocketExceptionon failure of setsockopt(IP_DROP_MEMBERSHIP).

◆ leaveGroupIPv6()

void jsocketpp::SocketOptions::leaveGroupIPv6 ( in6_addr group,
unsigned int ifindex )

Leave a previously joined IPv6 multicast group on a specific interface index.

Parameters
[in]groupIPv6 multicast group address.
[in]ifindexInterface index used when joining.
Exceptions
SocketExceptionon failure of IPV6_LEAVE_GROUP (POSIX) or IPV6_DROP_MEMBERSHIP (Windows).

◆ operator=() [1/2]

SocketOptions & jsocketpp::SocketOptions::operator= ( const SocketOptions & )
delete

Copy assignment operator (deleted) for SocketOptions.

The copy assignment operator is explicitly deleted to prevent reassignment between SocketOptions instances. Copying would duplicate the socket handle without transferring ownership, leading to potential issues such as:

  • Double close() calls on the same socket
  • Confusing ownership semantics
  • Race conditions in multithreaded environments

This deletion is consistent with the rest of the socket library, where all socket classes are designed to be non-copyable and resource-owning via RAII.

Note
Use move assignment (operator=(SocketOptions&&)) to transfer ownership safely.
SocketOptions a(sockFd);
b = a; // ❌ Compilation error (copy assignment is deleted)
SocketOptions()=delete
Default constructor (deleted) for SocketOptions base class.
See also
operator=(SocketOptions&&) noexcept

◆ operator=() [2/2]

SocketOptions & jsocketpp::SocketOptions::operator= ( SocketOptions && )
defaultnoexcept

Move assignment operator for SocketOptions.

Transfers the socket handle (_sockFd) and internal state from another SocketOptions instance to this one. Any existing state in the current object is overwritten. The moved-from object is left in a valid but unspecified state (usually with _sockFd == INVALID_SOCKET).

This operator supports efficient reassignment of socket resources in derived classes while preserving RAII guarantees and preventing resource leaks.

Rationale

  • Allows efficient reassignment of socket wrappers
  • Ensures only one object retains ownership of the socket handle
  • Preserves safe ownership semantics across the library
Warning
The moved-from object should not be used after assignment.
SocketOptions a(sockFd1);
SocketOptions b(sockFd2);
b = std::move(a); // ✅ b now owns sockFd1, sockFd2 is released or overwritten
See also
SocketOptions(SocketOptions&&) noexcept

◆ setBroadcast()

void jsocketpp::SocketOptions::setBroadcast ( bool on)

Enables or disables the ability to send UDP broadcast messages.

This method sets the SO_BROADCAST socket option, which allows the socket to send datagrams to broadcast addresses (e.g., 255.255.255.255 or 192.168.1.255).


🌍 Applicability


🔐 Platform Behavior

  • Most OSes require SO_BROADCAST = 1 before sending to broadcast addresses
  • Without it, sendto() to a broadcast address may fail with EACCES or Permission denied

Use Cases

  • UDP service discovery (e.g., mDNS, SSDP)
  • Device presence announcements
  • Peer-to-peer local communication

Example

DatagramSocket sock(AF_INET);
sock.setBroadcast(true);
sock.bind("0.0.0.0", 0);
sockaddr_in broadcastAddr = {};
broadcastAddr.sin_family = AF_INET;
broadcastAddr.sin_port = htons(12345);
inet_pton(AF_INET, "255.255.255.255", &broadcastAddr.sin_addr);
sock.sendTo("Hello LAN", reinterpret_cast<sockaddr*>(&broadcastAddr), sizeof(broadcastAddr));
Cross-platform UDP socket class with Java-style interface.
Definition DatagramSocket.hpp:484

Parameters
[in]ontrue to enable broadcast permission, false to disable it.
Exceptions
SocketExceptionif:
  • The socket is invalid
  • The option is not supported by the socket type
  • The system call fails (e.g., EBADF, ENOPROTOOPT, EACCES)
See also
getBroadcast()
https://man7.org/linux/man-pages/man7/socket.7.html

◆ setIPv6Only()

void jsocketpp::SocketOptions::setIPv6Only ( bool enable)

Enables or disables IPV6_V6ONLY mode for IPv6-capable sockets.

This method configures the IPV6_V6ONLY socket option, which determines whether an IPv6 socket can accept only IPv6 connections or both IPv6 and IPv4-mapped addresses (e.g., ::ffff:a.b.c.d).


🌍 Applicability by Socket Type

  • ServerSocket: ✅ Common — determines which protocols are accepted via bind()
  • Socket: ✅ Optional — may control behavior of outgoing connections or bound local endpoint
  • DatagramSocket: ✅ Applies when binding to :: for dual-stack multicast or receiving
  • UnixSocket: ❌ Not applicable — local domain sockets do not use IP protocols

🔀 Platform Behavior

  • Linux: IPV6_V6ONLY defaults to 0 (dual-stack enabled)
  • Windows: Defaults to 1 (IPv6-only); must disable explicitly for dual-stack
  • macOS / BSD: Often defaults to 1, some systems disallow disabling

⚠️ On all platforms, this option must be set before bind(). Changing it afterward is undefined or ignored.


💡 Use Cases

  • Enforce strict IPv6-only policy (security or protocol compliance)
  • Enable dual-stack sockets that handle both IPv6 and IPv4 transparently
  • Configure UDP or multicast receivers to receive from both protocol families

Example

ServerSocket server(AF_INET6);
server.setIPv6Only(true); // Only allow IPv6 clients
server.bind("::", 8080);
server.listen();
TCP server socket abstraction for cross-platform C++ networking.
Definition ServerSocket.hpp:100

Parameters
[in]enabletrue to enable IPv6-only mode (IPV6_V6ONLY = 1), false to allow dual-stack operation (IPV6_V6ONLY = 0).
Exceptions
SocketExceptionif:
  • The socket is not valid
  • The option is unsupported on the platform or socket type
  • The system call (setsockopt()) fails
Note
This setting has no effect on UNIX domain sockets, and calling it on one will throw.
See also
getIPv6Only()
setOption()
https://man7.org/linux/man-pages/man7/ipv6.7.html

◆ setKeepAlive()

void jsocketpp::SocketOptions::setKeepAlive ( bool on)

Enables or disables TCP-level keepalive behavior on the socket (SO_KEEPALIVE).

Configures the SO_KEEPALIVE socket option, which instructs the operating system to periodically send keepalive probes on otherwise idle stream-oriented sockets. This helps detect half-open connections where the remote peer has silently disconnected, crashed, or become unreachable without sending a FIN or RST.

🔁 Applicability

  • TCP sockets (Socket): Fully supported and commonly used.
  • UNIX domain stream sockets (UnixSocket): Supported on most POSIX platforms.
  • Accepted client sockets in ServerSocket: Enable per-socket after accept().
  • ⚠️ UDP or datagram sockets (DatagramSocket): Not applicable. Most systems ignore this flag.

Platform Behavior

  • Linux: Keepalive timing is controlled by /proc/sys/net/ipv4/tcp_keepalive_* parameters. Per-socket tuning (e.g., idle, interval, probes) is available using advanced options (not exposed here).
  • Windows: Default timeout is ~2 hours. Fine-tuning requires WSAIoctl with SIO_KEEPALIVE_VALS.
  • macOS/BSD: Controlled by system-level TCP settings; per-socket control is limited.

Effects

  • If enabled (on == true), the OS sends periodic probes on idle connections. If the peer does not respond after several attempts, the connection is forcefully closed.
  • If disabled (on == false), no keepalive probes are sent. The socket may remain open indefinitely.

Example

socket.setKeepAlive(true); // Enable periodic liveness checks on TCP
Parameters
[in]onSet to true to enable keepalive, or false to disable it.
Exceptions
SocketExceptionif:
  • The socket is invalid
  • SO_KEEPALIVE is unsupported for this socket type
  • The system call fails due to platform-level constraints
See also
getKeepAlive()
setOption()
https://man7.org/linux/man-pages/man7/tcp.7.html
Note
This method does not configure the keepalive timing parameters (interval, probes, timeout). Use platform-specific APIs for advanced tuning.

◆ setMulticastInterfaceIPv4()

void jsocketpp::SocketOptions::setMulticastInterfaceIPv4 ( in_addr addr)

Select the outgoing IPv4 interface for multicast.

Sets the per-socket default egress interface used for IPv4 multicast transmissions. For IPv4, the egress is specified by the interface’s unicast IPv4 address. Passing INADDR_ANY (in network byte order) restores the system default route.

This call affects only outbound multicast selection for the IPv4 family; it does not join or leave any multicast group, and it does not affect IPv6.

Parameters
[in]addrIPv4 address (network byte order) of the desired egress interface. Use in_addr{ .s_addr = htonl(INADDR_ANY) } to reset to the system default.
Precondition
  • The underlying descriptor is a valid UDP-capable socket opened for AF_INET or capable of IPv4 multicast sends (e.g., dual-stack if supported).
Postcondition
  • The socket’s default IPv4 multicast egress interface is updated. Subsequent IPv4 multicast sends on this socket will use the selected interface until changed again or reset to default.
Platform mapping
  • setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, ...)
    • POSIX: value is a struct in_addr (network byte order).
    • Windows: value is a DWORD containing the IPv4 address in network byte order.
Error conditions
  • The socket is invalid or closed.
  • The specified address is malformed or otherwise rejected by the OS.
  • The underlying setsockopt(IP_MULTICAST_IF) fails (e.g., ENOTSOCK, EINVAL, ENOPROTOOPT; Windows: WSAENOTSOCK, WSAEINVAL, WSAENOPROTOOPT).
Exceptions
SocketExceptionIf the option cannot be applied. The exception carries the OS error code and a descriptive message produced by SocketErrorMessage(...).
Note
  • This function does not verify that addr is currently assigned to a local interface. Some stacks may accept the option but later fail to send if routing is not feasible. Prefer to pass an address you know is bound to a local interface.
  • This setting is per-socket and only influences multicast egress selection. It does not affect unicast routing nor which local interfaces receive multicast (reception depends on group membership on each socket).
  • For IPv6 multicast egress, use setMulticastInterfaceIPv6(unsigned int).
  • Higher-level convenience: if you need to accept human-friendly identifiers (empty string, IPv4 literal, IPv6 index/name on POSIX), consider using setMulticastInterface(const std::string&).
Related options
// Example: choose IPv4 egress by literal
in_addr eg{};
if (inet_pton(AF_INET, "192.0.2.10", &eg) != 1) {
throw std::runtime_error("invalid IPv4 address");
}
sock.setMulticastInterfaceIPv4(eg);
// Example: reset to default IPv4 multicast egress
in_addr any{}; any.s_addr = htonl(INADDR_ANY);
sock.setMulticastInterfaceIPv4(any);

◆ setMulticastInterfaceIPv6()

void jsocketpp::SocketOptions::setMulticastInterfaceIPv6 ( unsigned int ifindex)

Select the outgoing IPv6 interface for multicast.

Sets the per-socket default egress interface used for IPv6 multicast transmissions by specifying a numeric interface index. Passing 0 resets to the system default route.

This call affects only outbound IPv6 multicast selection; it does not join or leave any multicast group and does not affect IPv4 egress.

Parameters
[in]ifindexIPv6 interface index for multicast egress. Use 0 to restore the system default. On POSIX systems you can obtain this via if_nametoindex().
Precondition
  • The underlying descriptor is a valid UDP-capable socket (typically AF_INET6 or dual-stack if enabled).
Postcondition
  • The socket’s default IPv6 multicast egress interface is updated. Subsequent IPv6 multicast sends from this socket will use the selected interface until changed again or reset to default.
Platform mapping
  • setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex))
    • Windows: ifindex is passed as a DWORD.
    • POSIX: ifindex is an unsigned int (commonly the value returned by if_nametoindex()).
Error conditions
  • The socket is invalid or closed.
  • The specified interface index is not valid on this host.
  • The underlying setsockopt(IPV6_MULTICAST_IF) call fails (e.g., ENOTSOCK, EINVAL, ENOPROTOOPT; Windows: WSAENOTSOCK, WSAEINVAL, WSAENOPROTOOPT).
Exceptions
SocketExceptionIf the option cannot be applied. The exception carries the OS error code and a descriptive message produced by SocketErrorMessage(...).
Note
  • This setting is per-socket and influences only multicast egress selection for IPv6. It does not affect unicast routing nor which local interfaces receive multicast—reception depends on group membership on each socket.
  • On Windows, interface names are not accepted for IPV6_MULTICAST_IF; provide a numeric index. On POSIX, you may convert an interface name via if_nametoindex().
  • If the socket was created with IPV6_V6ONLY enabled, this setting applies only to the IPv6 path; it does not influence IPv4 multicast egress.
Related options
// POSIX: choose IPv6 egress by interface name
unsigned int idx = if_nametoindex("eth0");
if (idx == 0) { throw SocketException("Unknown interface: eth0"); }
sock.setMulticastInterfaceIPv6(idx);
// Windows (or any platform): choose egress by numeric index
sock.setMulticastInterfaceIPv6(12); // where 12 is the adapter's IPv6 index
// Reset to default IPv6 multicast egress
sock.setMulticastInterfaceIPv6(0);

◆ setMulticastLoopback()

void jsocketpp::SocketOptions::setMulticastLoopback ( bool enable)

Enable or disable multicast loopback for this socket.

Controls whether multicast datagrams transmitted by this socket are delivered back to the local host (“looped back”). This affects only local delivery; it does not influence what remote receivers get.

  • IPv4: maps to IP_MULTICAST_LOOP.
  • IPv6: maps to IPV6_MULTICAST_LOOP.

Semantics (effective for packets sent by this socket):

  • enable == true (loopback on): the kernel may deliver a local copy of each outbound multicast to sockets on the same host that have joined the group (including this socket, if it has joined).
  • enable == false (loopback off): the kernel suppresses local delivery of those packets on this host—no local socket will receive the copies of this socket’s outbound multicast frames.

This setting is per-socket and applies to subsequent sends until changed. It does not affect unicast traffic, and it does not force other sockets to receive or drop multicast that originates elsewhere.

Parameters
[in]enabletrue to enable local loopback of this socket’s multicast transmissions; false to suppress local loopback.
Precondition
  • The underlying descriptor is a valid datagram (UDP) socket created for AF_INET or AF_INET6.
Postcondition
  • The socket’s multicast loopback policy is updated. Future multicast sends from this socket follow the new policy; in-flight packets are unaffected.
Platform mapping
  • IPv4: setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &flag, sizeof(flag))
  • IPv6: setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &flag, sizeof(flag))
Error conditions
  • The socket is invalid or closed.
  • The socket family cannot be determined or is unsupported on this platform.
  • The underlying setsockopt fails (e.g., ENOTSOCK, ENOPROTOOPT, EINVAL, or Windows equivalents WSAENOTSOCK, WSAENOPROTOOPT, WSAEINVAL).
Exceptions
SocketExceptionIf the option cannot be set for any of the reasons above. The exception includes the OS error code and a descriptive message from SocketErrorMessage(...).
Note
  • Typical default is enabled (1) on most stacks, but it is implementation-defined; call getMulticastLoopback() to confirm.
  • Disabling loopback is useful when a sender also listens on the same group and you want to avoid processing your own announcements.
  • This control concerns local delivery only; it has no impact on what remote hosts receive.
Related options
// Example: avoid receiving our own announcements
sock.setMulticastInterface("eth0");
sock.joinGroup("239.1.2.3");
sock.setMulticastLoopback(false); // suppress local copies of our sends
sock.sendTo("239.1.2.3", 5000, payload);
Cross-platform multicast UDP socket class (IPv4/IPv6).
Definition MulticastSocket.hpp:75
void setMulticastLoopback(bool enable)
Enable or disable multicast loopback for this socket.
Definition SocketOptions.cpp:425
void joinGroup(const std::string &groupAddr, const std::string &iface)
Join a multicast group on an optional interface (string-friendly).
Definition MulticastSocket.cpp:173
void setMulticastInterface(const std::string &iface)
Select the default outgoing interface for multicast transmissions.
Definition MulticastSocket.cpp:20

◆ setMulticastTTL()

void jsocketpp::SocketOptions::setMulticastTTL ( int ttl)

Set the default multicast hop limit / TTL for this socket.

Sets the per-socket default scope for multicast transmissions:

  • For IPv4 sockets, maps to IP_MULTICAST_TTL (time-to-live).
  • For IPv6 sockets, maps to IPV6_MULTICAST_HOPS (hop limit).

The value controls how far outbound multicast packets may travel:

  • 0 confines delivery to the local host (no transmission beyond the sender).
  • 1 confines delivery to the local link / subnet.
  • Higher values permit traversal across additional multicast routers up to the limit.

This setting applies to subsequent multicast sends on this socket until changed again. It does not affect unicast traffic—use IP_TTL / IPV6_UNICAST_HOPS for that.

Parameters
[in]ttlHop limit (IPv6) or TTL (IPv4), in the range [0, 255].
Precondition
  • The underlying socket must be a valid IPv4 (AF_INET) or IPv6 (AF_INET6) socket.
  • The socket is intended for multicast transmission (typically a datagram/UDP socket).
Postcondition
  • The socket’s default multicast TTL / hop limit is updated; subsequent multicast transmissions use this value unless a per-message override is supplied via ancillary data (e.g., IP_MULTICAST_TTL / IPV6_HOPLIMIT control messages).
Platform mapping
  • IPv4: setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, ...)
  • IPv6: setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ...)
Error conditions
  • ttl is outside [0, 255].
  • The socket is invalid or closed.
  • The socket family is unsupported for multicast TTL/hops on the current platform.
  • The underlying setsockopt call fails (e.g., ENOTSOCK, EINVAL, ENOPROTOOPT, or their Windows equivalents such as WSAENOTSOCK, WSAEINVAL, WSAENOPROTOOPT).
Exceptions
SocketExceptionIf ttl is out of range, the socket state is invalid, or the operating system rejects the option. The exception contains the OS error code and a descriptive message produced by SocketErrorMessage(...).
Note
  • This is a per-socket default. If your application uses sendmsg with ancillary data to specify a hop limit/TTL per packet, those per-message values take precedence.
  • Changing this value concurrently with active sends may produce a mix of old and new limits across packets that are in-flight during the update; set it during initialization for deterministic behavior.
Related options
// Example: restrict multicast to the local link and send
MulticastSocket sock; // or your UDP-capable socket wrapper
sock.setMulticastInterface("eth0"); // choose an egress interface
sock.setMulticastTTL(1); // 1 = link-local only
sock.joinGroup("239.1.2.3"); // join if you also receive on this socket
sock.sendTo("239.1.2.3", 5000, dataSpan);
void setMulticastTTL(int ttl)
Set the default multicast hop limit / TTL for this socket.
Definition SocketOptions.cpp:394

◆ setNonBlocking()

void jsocketpp::SocketOptions::setNonBlocking ( bool nonBlocking)

Enables or disables non-blocking mode on the socket.

This method configures the I/O blocking behavior of the socket. In non-blocking mode, system calls such as read(), write(), connect(), and accept() return immediately if they cannot proceed, rather than blocking the calling thread. This enables asynchronous or event-driven designs where the application explicitly manages readiness.

In blocking mode (the default), these calls block the thread until they complete, time out (if configured), or fail.


🔀 Platform Behavior

  • POSIX: Uses fcntl() to set or clear the O_NONBLOCK flag.
  • Windows: Uses ioctlsocket() with the FIONBIO control code.
  • Effect: Changes apply immediately and persist for the life of the socket.

📦 Applicable Socket Types

This operation is available on all socket types in this library:


⏱️ Behavior Summary by Operation

Operation In Blocking Mode In Non-Blocking Mode
connect() Blocks until connected or timeout Returns immediately; may require polling write
read() Waits for data or EOF Returns -1 with EWOULDBLOCK if no data
write() Waits for buffer availability Returns -1 if buffer full
accept() Waits for pending connection Returns -1 with EWOULDBLOCK if none available
recvfrom() Waits for incoming datagram Returns -1 if no datagram received

✅ Use Cases

  • Event-driven I/O (with select, poll, epoll, or kqueue)
  • GUI or game loops that must avoid blocking the main thread
  • High-performance servers handling thousands of concurrent clients
  • Real-time systems with custom scheduling and retry logic

Example: Enable non-blocking mode on a client socket

Socket sock("example.com", 80);
sock.setNonBlocking(true);
if (!sock.waitReady(true, 3000)) {
throw TimeoutException("Connection timed out");
}
TCP client connection abstraction (Java-like interface).
Definition Socket.hpp:93

Parameters
[in]nonBlockingtrue to enable non-blocking mode, false to restore blocking mode.
Exceptions
SocketExceptionif:
  • The socket is invalid (EBADF)
  • Platform-specific system calls fail
  • Permissions or capabilities are insufficient
Note
This setting only affects the current socket instance. It does not affect sockets returned by accept() (you must call setNonBlocking() on each accepted socket).
See also
getNonBlocking()
waitReady() To wait for readiness in non-blocking mode
setSoRecvTimeout() For timeout control in blocking mode

◆ setOption() [1/2]

void jsocketpp::SocketOptions::setOption ( int level,
int optName,
const void * value,
socklen_t len )

Sets a low-level socket option using a structured or binary value.

This overload of setOption() configures advanced socket options that require passing complex values via a memory buffer, such as struct linger, protocol-specific flags, or platform-defined structures.

Socket options allow advanced users to customize performance, transport behavior, and resource usage. This method is applicable to all supported socket types:

It supports options at various protocol levels, including:

  • SOL_SOCKET for generic socket behavior
  • IPPROTO_TCP for TCP-specific options
  • IPPROTO_UDP, IPPROTO_IP, etc.

🧩 Use Cases

  • Configure linger behavior with SO_LINGER using struct linger
  • Apply platform-specific options that require binary data
  • Set multicast interface (IP_MULTICAST_IF) or IPv6 options

Example: Set SO_LINGER to linger for 5 seconds on close

linger lin;
lin.l_onoff = 1;
lin.l_linger = 5;
socket.setOption(SOL_SOCKET, SO_LINGER, &lin, sizeof(linger));

⚠️ ServerSocket-specific Notes

  • Only affects the passive/listening socket itself.
  • Accepted sockets must be configured separately.

📡 DatagramSocket-specific Notes

  • Can be used for multicast, broadcast, timeouts, etc.
  • Accepts raw buffers for protocol-level socket options.

🧿 UnixSocket-specific Notes

  • Common options include SO_PASSCRED, SO_RCVBUF, SO_SNDTIMEO
  • TCP-specific options (e.g., TCP_NODELAY) are not supported.

Parameters
[in]levelProtocol level (e.g., SOL_SOCKET, IPPROTO_TCP)
[in]optNameOption name (e.g., SO_LINGER, IP_TOS)
[in]valuePointer to a buffer containing the option value
[in]lenSize of the buffer in bytes
Exceptions
SocketExceptionif:
  • The socket is invalid
  • setsockopt() fails due to invalid parameters or unsupported option
Note
This method is intended for structured or binary values. For simple integer options, use setOption(int, int, int) instead.
See also
setOption(int, int, int)
getOption(int, int, void*, socklen_t*)
https://man7.org/linux/man-pages/man2/setsockopt.2.html

◆ setOption() [2/2]

void jsocketpp::SocketOptions::setOption ( int level,
int optName,
int value )

Sets a low-level socket option on the underlying socket.

This method configures a socket option using the system-level setsockopt() interface. Socket options allow advanced users to fine-tune behavior related to performance, protocol semantics, reliability, and resource usage.

This API is available on all socket types provided by the library, including:

It supports options at multiple protocol levels, such as SOL_SOCKET, IPPROTO_TCP, and IPPROTO_UDP.


🔧 Common Use Cases

  • Enable address reuse (SO_REUSEADDR) for TCP/UDP servers
  • Enable TCP keepalive (SO_KEEPALIVE) for long-lived connections
  • Tune send/receive buffer sizes (SO_SNDBUF, SO_RCVBUF)
  • Disable Nagle’s algorithm (TCP_NODELAY) for latency-sensitive TCP clients
  • Enable broadcast mode (SO_BROADCAST) on UDP sockets

⚠️ ServerSocket-specific Notes

  • Setting options on a listening socket only affects the acceptor socket.
  • Options do not propagate to client sockets returned by accept().
  • Common use: SO_REUSEADDR before bind().
serverSocket.setOption(SOL_SOCKET, SO_REUSEADDR, 1);

📡 DatagramSocket-specific Notes

  • Useful for enabling SO_BROADCAST, tuning buffer sizes, or applying timeouts (SO_RCVTIMEO, SO_SNDTIMEO)
  • For connected UDP sockets, options affect the single remote peer.
  • For unconnected sockets, they apply to all traffic.
datagramSocket.setOption(SOL_SOCKET, SO_BROADCAST, 1);

🧿 UnixSocket-specific Notes

  • Although not TCP/IP-based, many SOL_SOCKET options apply:
    • SO_RCVBUF, SO_SNDBUF (buffer tuning)
    • SO_PASSCRED (credential passing)
    • SO_RCVTIMEO, SO_SNDTIMEO (timeouts)
  • TCP-level options like TCP_NODELAY are not supported.
unixSocket.setOption(SOL_SOCKET, SO_SNDBUF, 65536);

Parameters
[in]levelThe protocol level at which the option resides (e.g., SOL_SOCKET, IPPROTO_TCP).
[in]optNameThe name of the socket option (e.g., SO_REUSEADDR, TCP_NODELAY).
[in]valueInteger value to assign to the option.
Exceptions
SocketExceptionif:
  • The socket is invalid
  • setsockopt() fails due to unsupported option or platform error
See also
getOption(int, int) For querying current option values
setOption(int, int, const void*, socklen_t) For structured or binary options
https://man7.org/linux/man-pages/man2/setsockopt.2.html

◆ setReceiveBufferSize()

void jsocketpp::SocketOptions::setReceiveBufferSize ( std::size_t size)

Sets the socket's receive buffer size (SO_RCVBUF).

Configures the size of the kernel-level receive buffer for the underlying socket. This buffer controls how much data the operating system can queue before the application reads from the socket. Increasing this value can reduce packet loss and improve throughput under high load or network delay.

Applicability

This method is valid for all supported socket types:

  • TCP (Socket): Recommended for high-latency or high-throughput connections.
  • UDP (DatagramSocket): Critical for avoiding packet drops in high-volume flows.
  • UNIX domain sockets: Supported on most platforms.
  • ServerSocket: Affects the passive socket itself, not accepted clients.

Platform Behavior

  • Linux: The kernel typically doubles the requested size to account for internal overhead.
  • Windows: Value may be rounded to OS-specific granularity.
  • macOS/BSD: Follows BSD semantics; may enforce stricter limits.
  • In all cases, system-wide limits apply (e.g., /proc/sys/net/core/rmem_max on Linux).

Example

datagramSocket.setReceiveBufferSize(256 * 1024); // Set 256 KB buffer
int actual = datagramSocket.getReceiveBufferSize();
std::cout << "OS applied buffer size: " << actual << " bytes\n";
Parameters
[in]sizeDesired receive buffer size in bytes. Actual value may be adjusted by the OS.
Exceptions
SocketExceptionif:
  • The socket is invalid or uninitialized
  • The call to setsockopt() fails
  • The requested size exceeds system limits
  • Insufficient permissions to increase buffer limits
Note
Always call this after socket creation and before heavy I/O.
See also
getReceiveBufferSize()
setSendBufferSize()
setInternalBufferSize()

◆ setReuseAddress()

void jsocketpp::SocketOptions::setReuseAddress ( bool on)

Enables or disables the SO_REUSEADDR socket option.

This option controls whether the socket is permitted to bind to a local address and port that is already in use or in the TIME_WAIT state. It is commonly used in both server and client contexts, and is applicable to TCP, UDP, and Unix domain sockets.

Internally, this method invokes:

setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, ...)

Platform Behavior

  • POSIX (Linux, BSD, macOS):
    • Permits multiple sockets to bind the same address/port as long as all use SO_REUSEADDR.
    • Commonly used with multicast UDP, and for servers that need to restart quickly.
  • Windows:
    • Allows rebinding to a port in TIME_WAIT, but does not allow simultaneous binds.
    • Microsoft recommends SO_EXCLUSIVEADDRUSE for exclusive ownership, but SO_REUSEADDR works for most cases.

Protocol Use Cases

  • TCP Server Sockets: Enables re-binding to a port immediately after shutdown.
  • TCP Client Sockets: Useful when binding to a fixed local port to reconnect rapidly.
  • UDP Sockets:
    • Allows multiple sockets to bind to the same port, often required for multicast listeners.
    • Useful in P2P setups where port reuse is desired across short-lived sessions.
  • Unix Domain Sockets:
    • On some platforms, SO_REUSEADDR may be ignored or unnecessary for AF_UNIX, since file system semantics already handle path reusability. However, setting it is harmless and may be supported by your platform for consistency.

Example

socket.setReuseAddress(true); // Enable port/path reuse before calling bind()
Warning
This method must be called after socket creation and before bind(). Improper use can lead to security issues or interference between applications.
Parameters
[in]onIf true, enables address reuse; if false, disables it.
Exceptions
SocketExceptionif the socket is invalid or the option cannot be set.
See also
getReuseAddress()
bind()
https://man7.org/linux/man-pages/man7/socket.7.html

◆ setReusePort()

void jsocketpp::SocketOptions::setReusePort ( const bool enable)

Enables or disables the SO_REUSEPORT socket option.

This method configures the SO_REUSEPORT option, which allows multiple sockets to bind to the same IP address and port combination, enabling parallelism in multi-threaded or multi-process applications. Unlike SO_REUSEADDR, which allows re-binding during TIME_WAIT, SO_REUSEPORT permits simultaneous binding by multiple sockets.


🌍 Applicability

  • ServerSocket: ✅ Enables load-balanced accept loops across threads or processes
  • DatagramSocket: ✅ Permits shared reception on a multicast port (platform-dependent)
  • Socket: ✅ Technically allowed, but rarely used in clients
  • UnixSocket: ❌ Not supported; this method is not compiled on unsupported platforms

🔀 Platform Support

  • ✅ Linux (kernel ≥ 3.9)
  • ✅ BSD-based systems (FreeBSD, macOS)
  • ❌ Windows: Not available — this method is excluded at compile time

Example: Enable shared port binding

#if defined(SO_REUSEPORT)
serverSocket.setReusePort(true);
serverSocket.bind("0.0.0.0", 8080);
serverSocket.listen();
#endif

Parameters
[in]enabletrue to allow multiple sockets to bind the same port (SO_REUSEPORT = 1), or false to disable the shared binding behavior (SO_REUSEPORT = 0).
Exceptions
SocketExceptionif:
  • The socket is invalid
  • The system call fails (setsockopt() error)
  • The option is used improperly (e.g., after bind())
Note
This option must be set before calling bind(). Behavior is undefined if changed after binding.
See also
getReusePort()
setReuseAddress()
https://lwn.net/Articles/542629/

◆ setSendBufferSize()

void jsocketpp::SocketOptions::setSendBufferSize ( std::size_t size)

Sets the socket's send buffer size (SO_SNDBUF).

Configures the size of the kernel-level send buffer for this socket. This buffer controls how much data the operating system can queue for transmission before blocking the sender or returning a partial write. Larger buffers help improve throughput, especially in high-bandwidth or high-latency network environments.

Applicability

This method is valid for all socket types:

  • TCP (Socket): Helps reduce application-level blocking and improves write throughput.
  • UDP (DatagramSocket): Allows higher burst rate; excess data is dropped if full.
  • UNIX domain sockets: Supported for local IPC buffering on most systems.
  • ServerSocket: Setting this has no meaningful effect on passive sockets.

Platform Behavior

  • Linux: Kernel may double the size for internal overhead; limited by /proc/sys/net/core/wmem_max.
  • Windows: Rounded to system-specific page sizes or segment alignment.
  • BSD/macOS: Honors the request up to system-imposed limits.
  • All platforms may silently apply a different size than requested — verify with getSendBufferSize().

Example

socket.setSendBufferSize(128 * 1024); // 128 KB buffer
int actual = socket.getSendBufferSize();
std::cout << "Effective send buffer: " << actual << " bytes\n";
Parameters
[in]sizeDesired send buffer size in bytes. The actual buffer size may be adjusted by the system.
Exceptions
SocketExceptionif:
  • The socket is invalid or uninitialized
  • The call to setsockopt() fails
  • The requested size exceeds system-imposed limits
  • Insufficient privileges are present
Note
Applies to future sends only; does not affect buffered data already enqueued.
See also
getSendBufferSize()
setReceiveBufferSize()
setInternalBufferSize()

◆ setSocketFd()

void jsocketpp::SocketOptions::setSocketFd ( const SOCKET sock)
inlineprotectednoexcept

Updates the socket descriptor used by this object.

This method sets the internal socket file descriptor used by the SocketOptions interface. It is typically called by derived classes after the socket has been moved, reassigned, or otherwise changed during the object's lifetime.

This does not open, close, or validate the socket descriptor. It simply updates the internal _sockFd used by methods such as setOption() and getOption().

When to Use

  • After a move constructor or move assignment updates the underlying socket
  • After explicitly re-binding or re-creating a socket file descriptor
  • When adapting an externally provided descriptor (e.g., from accept() or socketpair())

Example: Move assignment

_sockFd = rhs._sockFd;
setSocketFd(_sockFd); // keeps SocketOptions base class in sync
SOCKET _sockFd
Underlying socket file descriptor.
Definition SocketOptions.hpp:2488
void setSocketFd(const SOCKET sock) noexcept
Updates the socket descriptor used by this object.
Definition SocketOptions.hpp:2281
Parameters
[in]sockThe new socket file descriptor to associate with this object. May be INVALID_SOCKET to mark the socket as uninitialized or closed.
Note
This method does not perform error checking. It is the caller's responsibility to ensure the provided descriptor is valid and consistent with the derived class state.
See also
getOption()
setOption()
SocketOptions

◆ setSoLinger()

void jsocketpp::SocketOptions::setSoLinger ( bool enable,
int seconds )

Configures the socket's linger behavior (SO_LINGER) during close.

This method sets the SO_LINGER socket option, which controls how the socket behaves when it is closed and unsent data remains in the transmission buffer. It determines whether close() will return immediately (discarding unsent data), or block until the data is transmitted or a timeout expires.

🔁 Applicability

  • TCP (Socket): Fully supported; governs graceful vs. abortive close behavior.
  • UNIX stream sockets (UnixSocket): Supported on most platforms.
  • ⚠️ UDP or UNIX datagram sockets (DatagramSocket): Technically accepted by some systems, but SO_LINGER has no effect (ignored by the kernel).
  • ⚠️ ServerSocket (listening): Affects only the listening socket itself; accepted sockets must be configured separately.

Behavior

  • Linger enabled (enable == true):
    • The OS will try to send remaining data on close.
    • If data cannot be sent within seconds, the socket is closed forcibly.
    • A timeout of 0 causes an abortive close (TCP RST is sent immediately).
  • Linger disabled (enable == false) (default):
    • close() returns immediately.
    • Unsent data may be discarded depending on system behavior.

Example

// Wait up to 5 seconds for graceful shutdown
socket.setSoLinger(true, 5);
// Immediately discard unsent data on close (send TCP RST)
socket.setSoLinger(true, 0);
// Standard non-blocking close behavior
socket.setSoLinger(false, 0);
Parameters
[in]enableWhether to enable lingering behavior on close.
[in]secondsLinger timeout (in seconds). Only meaningful if enable == true.
  • Must be ≥ 0. 0 means abortive close.
Exceptions
SocketExceptionif:
  • The socket is invalid
  • setsockopt() fails
  • The operation is not supported on the socket type (platform-dependent)
See also
getSoLinger()
shutdown()
close()
Note
Behavior is OS-specific. On POSIX, applies only to stream-oriented sockets. On Windows, similar semantics apply via Winsock.

◆ setSoRecvTimeout()

void jsocketpp::SocketOptions::setSoRecvTimeout ( int millis)

Sets the socket receive timeout (SO_RCVTIMEO) in milliseconds.

This method configures how long a blocking read operation may wait for incoming data before timing out. It affects all socket types that perform blocking I/O, including:

A timeout of 0 disables the timeout entirely, causing read operations to block indefinitely until data is available, the connection is closed, or an error occurs. A negative timeout is invalid and will result in an exception.


🔀 Platform Behavior

  • Windows: The timeout is passed as an int in milliseconds.
  • POSIX: The timeout is passed as a struct timeval (seconds + microseconds).

Example: Set a 3-second receive timeout

socket.setSoRecvTimeout(3000); // Timeout after 3000 ms if no data arrives
std::string line = socket.readUntil('\n');

Parameters
[in]millisTimeout in milliseconds. Must be ≥ 0. Use 0 to disable the timeout.
Exceptions
SocketExceptionif:
  • The socket is invalid
  • The timeout is negative
  • setsockopt() fails due to unsupported option or system-level error
See also
getSoRecvTimeout()
setSoSendTimeout()
https://man7.org/linux/man-pages/man7/socket.7.html

◆ setSoSendTimeout()

void jsocketpp::SocketOptions::setSoSendTimeout ( int millis)

Sets the socket send timeout (SO_SNDTIMEO) in milliseconds.

This method configures how long a blocking send operation (e.g., write(), writeAll()) may block before timing out. It affects all socket types that support writing:

A timeout of 0 disables the timeout entirely, allowing send operations to block indefinitely until buffer space is available. A negative timeout is invalid and will result in an exception.


🔀 Platform Behavior

  • Windows: Timeout is set as a plain int in milliseconds.
  • POSIX: Timeout is specified via a struct timeval with second/microsecond precision.

Example: Set a 5-second send timeout

socket.setSoSendTimeout(5000); // Timeout if write blocks for more than 5 seconds
socket.writeAll(request);

Parameters
[in]millisTimeout in milliseconds. Must be ≥ 0. Use 0 to disable the timeout.
Exceptions
SocketExceptionif:
  • The socket is invalid
  • The timeout is negative
  • setsockopt() fails due to system-level error or unsupported option
See also
getSoSendTimeout()
setSoRecvTimeout()
https://man7.org/linux/man-pages/man7/socket.7.html

◆ setSoTimeout()

void jsocketpp::ServerSocket::setSoTimeout ( const int timeoutMillis)
inline

Set the logical timeout (in milliseconds) for accepting client connections.

This timeout applies to methods like accept() and tryAccept(), and determines how long the server socket will wait for a client connection before timing out.

Unlike Socket::setSoTimeout(), this method does not call setsockopt() and does not affect the underlying socket descriptor. Instead, it is used internally to control the behavior of select() during accept operations.

Note
Use:
  • Negative value: wait indefinitely (blocking behavior)
  • Zero: poll mode (non-blocking)
  • Positive value: wait up to the specified milliseconds
Parameters
timeoutMillisTimeout value in milliseconds
See also
getSoTimeout()
accept()
tryAccept()
waitReady()

◆ setTcpNoDelay()

void jsocketpp::SocketOptions::setTcpNoDelay ( bool on)

Enables or disables Nagle’s algorithm (TCP_NODELAY) on TCP sockets.

This method configures the TCP_NODELAY option, which controls the behavior of Nagle's algorithm for stream-oriented TCP sockets (SOCK_STREAM). Nagle's algorithm aims to reduce network congestion by delaying small outgoing packets until previous ones are acknowledged — effectively "coalescing" writes.

Disabling Nagle’s algorithm (i.e., setting TCP_NODELAY = 1) allows small packets to be sent immediately, which is ideal for latency-sensitive applications. Enabling it (i.e., setting TCP_NODELAY = 0) improves throughput by batching writes, but introduces potential delays.


💡 Use Cases

  • Latency-sensitive applications:
    • Games, remote control, real-time messaging, RPC
    • Disabling Nagle (on = true) minimizes delay in sending small payloads
  • Bulk transfer or high-throughput services:
    • Enabling Nagle (on = false) reduces packet count and improves network efficiency

🔀 Platform Behavior

  • Universally available on TCP/IP sockets (AF_INET, AF_INET6 with SOCK_STREAM)
  • POSIX: Uses setsockopt() with IPPROTO_TCP and TCP_NODELAY
  • Windows: Uses Winsock with same option names
  • Has no effect on:

Example: Disable Nagle’s algorithm to reduce latency

Socket sock("example.com", 443);
sock.connect();
sock.setTcpNoDelay(true); // Disable Nagle — send immediately
sock.write("small interactive packet");

Parameters
[in]onIf true, disables Nagle's algorithm (TCP_NODELAY = 1), enabling immediate sends. If false, enables Nagle's algorithm (TCP_NODELAY = 0) to batch small writes.
Exceptions
SocketExceptionif:
  • The socket is invalid or closed
  • The option is unsupported on the current socket type
  • The setsockopt() call fails due to system error or permission issue
Note
Calling this method on a non-TCP socket will raise an exception. You can catch SocketException to handle cross-socket behavior gracefully.
See also
getTcpNoDelay()
https://en.wikipedia.org/wiki/Nagle%27s_algorithm
https://man7.org/linux/man-pages/man7/tcp.7.html

◆ SocketOptions() [1/4]

jsocketpp::SocketOptions::SocketOptions ( )
delete

Default constructor (deleted) for SocketOptions base class.

This constructor is explicitly deleted to prevent the creation of uninitialized SocketOptions objects. Subclasses like Socket, ServerSocket, or DatagramSocket must initialize the socket handle explicitly via constructor arguments or system calls.

Rationale

  • Prevents misuse of base class in isolation
  • Enforces proper ownership semantics for _sockFd
  • Ensures all derived types have valid or explicitly invalid sockets
SocketOptions opt; // ❌ Compilation error (deleted constructor)
See also
SocketOptions(SOCKET) Constructor with explicit socket handle
close(), setSocketFd(), getSocketFd()

◆ SocketOptions() [2/4]

jsocketpp::SocketOptions::SocketOptions ( const SOCKET sock)
inlineexplicitnoexcept

Initializes the socket option interface with a specific socket descriptor.

Constructs a SocketOptions object that uses the provided socket file descriptor for all subsequent setOption() and getOption() calls. This constructor is intended to be used by derived socket classes (e.g., Socket, ServerSocket, UnixSocket) to delegate option-handling responsibilities without duplicating system-specific logic.

Parameters
[in]sockA valid socket descriptor (e.g., from socket(), accept(), etc.), or INVALID_SOCKET if the object is not yet initialized.
Note
It is the responsibility of the derived class to ensure that the socket descriptor remains valid for the lifetime of the SocketOptions object.
Warning
This class does not manage or close the socket descriptor. It assumes the derived class owns and controls the lifetime of the socket.
See also
setSocketFd()
setOption()
getOption()

◆ SocketOptions() [3/4]

jsocketpp::SocketOptions::SocketOptions ( const SocketOptions & )
delete

Copy constructor (deleted) for SocketOptions.

The copy constructor is explicitly deleted to prevent accidental copying of SocketOptions instances. Since the class wraps a native socket handle (SOCKET), copying it would result in multiple objects referring to the same socket, leading to unsafe behavior such as double-closing or unexpected side effects.

All derived socket classes in the library (e.g., Socket, ServerSocket, DatagramSocket) are also non-copyable to preserve strict ownership semantics and RAII guarantees.

Note
Use move semantics (SocketOptions(SocketOptions&&)) to transfer ownership explicitly.
SocketOptions a(sockFd);
SocketOptions b = a; // ❌ Compilation error (copy constructor is deleted)
See also
SocketOptions(SocketOptions&&) noexcept

◆ SocketOptions() [4/4]

jsocketpp::SocketOptions::SocketOptions ( SocketOptions && )
defaultnoexcept

Move constructor for SocketOptions.

Transfers the socket handle (_sockFd) and internal state from another SocketOptions instance. After the move, the source object is left in a valid but unspecified state (typically with _sockFd set to INVALID_SOCKET).

This enables safe and efficient transfer of socket ownership in derived classes, such as Socket, DatagramSocket, or ServerSocket, without invoking unnecessary system calls or duplicating file descriptors.

Rationale

  • Enables move semantics for socket objects
  • Prevents accidental use-after-move by invalidating the source _sockFd
  • Supports RAII-friendly container usage (e.g., std::vector<DatagramSocket>)
Warning
After the move, the source object should not be used for socket operations.
SocketOptions a(sockFd);
SocketOptions b = std::move(a); // ✅ Transfers socket handle to b
See also
operator=(SocketOptions&&) noexcept

◆ ~SocketOptions()

virtual jsocketpp::SocketOptions::~SocketOptions ( )
virtualdefault

Virtual destructor for safe polymorphic destruction.

Ensures that derived classes can be safely destroyed through a pointer to SocketOptions. This is important for preventing resource leaks and undefined behavior when using socket option interfaces polymorphically (e.g., in unit tests or abstraction layers).

This destructor does not perform any cleanup of the socket descriptor itself, as SocketOptions does not own or manage the socket lifecycle. Derived classes are responsible for closing or releasing the socket if needed.

Note
Declared virtual to support inheritance and polymorphism.