![]() |
jsocketpp 1.0
A cross-platform C++20 socket library.
|
Classes and functions for UDP datagram networking. More...

Classes | |
| struct | jsocketpp::DatagramReadOptions |
| Options controlling a single UDP receive operation. More... | |
| struct | jsocketpp::DatagramReadResult |
| Telemetry data about a single UDP datagram receive operation. More... | |
| struct | jsocketpp::ReadExactOptions |
| Policy for enforcing an exact-byte receive on a single UDP datagram. More... | |
| class | jsocketpp::DatagramPacket |
| Represents a UDP datagram packet, encapsulating both payload and addressing information. More... | |
| class | jsocketpp::DatagramSocket |
| Cross-platform UDP socket class with Java-style interface. More... | |
| class | jsocketpp::MulticastSocket |
| Cross-platform multicast UDP socket class (IPv4/IPv6). More... | |
Enumerations | |
| enum class | jsocketpp::DatagramReceiveMode : std::uint8_t { jsocketpp::DatagramReceiveMode::NoPreflight = 0 , jsocketpp::DatagramReceiveMode::PreflightSize = 1 , jsocketpp::DatagramReceiveMode::PreflightMax = 2 } |
| Receive-time sizing policy for UDP datagrams. More... | |
| enum class | jsocketpp::Direction : std::uint8_t { jsocketpp::Direction::Read , jsocketpp::Direction::Write , jsocketpp::Direction::ReadWrite } |
| I/O readiness selector used by waitReady(). More... | |
Functions | |
| bool | jsocketpp::DatagramPacket::hasDestination () const noexcept |
| Report whether this packet specifies an explicit destination (address + port). | |
| jsocketpp::DatagramSocket::DatagramSocket (Port localPort=0, std::string_view localAddress="", std::optional< std::size_t > recvBufferSize=std::nullopt, std::optional< std::size_t > sendBufferSize=std::nullopt, std::optional< std::size_t > internalBufferSize=std::nullopt, bool reuseAddress=true, int soRecvTimeoutMillis=-1, int soSendTimeoutMillis=-1, bool nonBlocking=false, bool dualStack=true, bool autoBind=true, bool autoConnect=false, std::string_view remoteAddress="", Port remotePort=0, int connectTimeoutMillis=-1) | |
| Creates a UDP socket, optionally binds to a local address, and optionally connects to a remote peer. | |
| jsocketpp::DatagramSocket::~DatagramSocket () noexcept override | |
| Destructor for DatagramSocket. Ensures socket resources are released. | |
| jsocketpp::DatagramSocket::DatagramSocket (const DatagramSocket &)=delete | |
| Copy constructor (deleted) for DatagramSocket. | |
| DatagramSocket & | jsocketpp::DatagramSocket::operator= (const DatagramSocket &)=delete |
| Copy assignment operator (deleted) for DatagramSocket. | |
| jsocketpp::DatagramSocket::DatagramSocket (DatagramSocket &&rhs) noexcept | |
| Move constructor for DatagramSocket. | |
| DatagramSocket & | jsocketpp::DatagramSocket::operator= (DatagramSocket &&rhs) noexcept |
| Move assignment operator for DatagramSocket. | |
| void | jsocketpp::DatagramSocket::bind () |
| Binds the datagram socket to all available interfaces on an ephemeral port. | |
| void | jsocketpp::DatagramSocket::bind (Port localPort) |
| Binds the datagram socket to a specific local port on all network interfaces. | |
| void | jsocketpp::DatagramSocket::bind (std::string_view localAddress, Port localPort) |
| Binds the datagram socket to a specific local IP address and port. | |
| bool | jsocketpp::DatagramSocket::isBound () const noexcept |
| Indicates whether the datagram socket has been explicitly bound to a local address or port. | |
| void | jsocketpp::DatagramSocket::connect (std::string_view host, Port port, int timeoutMillis) |
| Connect this UDP socket to a default peer (set the default destination). | |
| void | jsocketpp::DatagramSocket::disconnect () |
| Disconnect this UDP socket from its current default peer. | |
| bool | jsocketpp::DatagramSocket::isConnected () const noexcept |
| Indicates whether the datagram socket is connected to a specific remote peer. | |
| std::string | jsocketpp::DatagramSocket::getLocalIp (bool convertIPv4Mapped) |
| Return the local interface IP address for this UDP socket. | |
| Port | jsocketpp::DatagramSocket::getLocalPort () |
| Return the local UDP port this socket is bound to. | |
| std::string | jsocketpp::DatagramSocket::getLocalSocketAddress (bool convertIPv4Mapped) |
| Return the local endpoint as a single "ip:port" string. | |
| std::string | jsocketpp::DatagramSocket::getRemoteIp (bool convertIPv4Mapped) const |
| Return the remote peer IP address for this socket. | |
| Port | jsocketpp::DatagramSocket::getRemotePort () const |
| Return the remote peer UDP port for this socket. | |
| std::string | jsocketpp::DatagramSocket::getRemoteSocketAddress (bool convertIPv4Mapped) const |
| Return the remote endpoint as a single "ip:port" string. | |
| void | jsocketpp::DatagramSocket::write (std::string_view message) const |
| Send one UDP datagram to the currently connected peer (no pre-wait). | |
| template<typename T> | |
| void | jsocketpp::DatagramSocket::write (const T &value) const |
Send one UDP datagram whose payload is the raw object representation of value. | |
| void | jsocketpp::DatagramSocket::write (std::span< const std::byte > data) const |
| Send one UDP datagram to the connected peer from a raw byte span (no pre-wait). | |
| void | jsocketpp::DatagramSocket::writeAll (std::string_view message) const |
| Send one UDP datagram to the connected peer, waiting indefinitely for writability. | |
| template<typename T> | |
| void | jsocketpp::DatagramSocket::writePrefixed (const std::string_view payload) const |
| Send a length-prefixed UDP datagram to the connected peer from text bytes (no pre-wait). | |
| template<typename T> | |
| void | jsocketpp::DatagramSocket::writePrefixed (const std::span< const std::byte > payload) const |
| Send a length-prefixed UDP datagram to the connected peer from a byte span (no pre-wait). | |
| template<typename T> | |
| void | jsocketpp::DatagramSocket::writePrefixedTo (const std::string_view host, const Port port, const std::string_view payload) const |
| Send a length-prefixed UDP datagram to (host, port) from text bytes (unconnected path). | |
| template<typename T> | |
| void | jsocketpp::DatagramSocket::writePrefixedTo (const std::string_view host, const Port port, const std::span< const std::byte > payload) const |
| Send a length-prefixed UDP datagram to (host, port) from a byte span (unconnected path). | |
| void | jsocketpp::DatagramSocket::writev (std::span< const std::string_view > buffers) const |
| Send one UDP datagram to the connected peer by concatenating multiple fragments (no pre-wait). | |
| void | jsocketpp::DatagramSocket::writevAll (std::span< const std::string_view > buffers) const |
| Send one UDP datagram to the connected peer by concatenating multiple fragments, waiting indefinitely. | |
| void | jsocketpp::DatagramSocket::writeFrom (const void *data, std::size_t len) const |
| Send one UDP datagram to the connected peer from a raw memory buffer (no pre-wait). | |
| void | jsocketpp::DatagramSocket::writeWithTimeout (std::string_view data, int timeoutMillis) const |
Send one UDP datagram to the connected peer, waiting up to timeoutMillis for writability. | |
| void | jsocketpp::DatagramSocket::write (const DatagramPacket &packet) |
| Send one UDP datagram using a packet’s buffer and optional explicit destination. | |
| void | jsocketpp::DatagramSocket::writeTo (std::string_view host, Port port, std::string_view message) |
| Send one unconnected UDP datagram to (host, port) from text bytes (no pre-wait). | |
| void | jsocketpp::DatagramSocket::writeTo (std::string_view host, Port port, std::span< const std::byte > data) |
| Send one unconnected UDP datagram to (host, port) from a raw byte span (no pre-wait). | |
| template<typename T> | |
| void | jsocketpp::DatagramSocket::writeTo (const std::string_view host, const Port port, const T &value) const |
Send one unconnected UDP datagram to (host, port) containing the raw bytes of value. | |
| DatagramReadResult | jsocketpp::DatagramSocket::read (DatagramPacket &packet, const DatagramReadOptions &opts) const |
| Read one UDP datagram into a DatagramPacket with optional growth/shrink and strict truncation policy. | |
| DatagramReadResult | jsocketpp::DatagramSocket::readInto (void *buffer, std::size_t len, const DatagramReadOptions &opts={}) const |
| Read one UDP datagram into a caller-provided buffer with explicit truncation policy. | |
| DatagramReadResult | jsocketpp::DatagramSocket::readInto (std::span< char > out, const DatagramReadOptions &opts={}) const |
| Read one UDP datagram into a caller-provided span (zero allocation) with explicit truncation policy. | |
| template<typename T, std::enable_if_t< detail::is_dynamic_buffer_v< T >, int > = 0> | |
| T | jsocketpp::DatagramSocket::read (const DatagramReadOptions &opts={}, std::size_t minCapacity=DefaultDatagramReceiveSize) const |
| Read one UDP datagram into a dynamically resizable, contiguous byte container (zero-copy into caller storage). | |
| template<typename T, std::enable_if_t< detail::is_fixed_buffer_v< T >, int > = 0> | |
| T | jsocketpp::DatagramSocket::read (const DatagramReadOptions &opts={}) const |
| Read one UDP datagram into a fixed-size, contiguous byte container (zero allocation). | |
| template<typename T> | |
| DatagramReadResult | jsocketpp::DatagramSocket::readFrom (T &buffer, std::string *senderAddr, Port *senderPort, const DatagramReadOptions &opts) const |
| Read one UDP datagram into a caller-provided byte container and optionally return the sender address/port. | |
| DatagramReadResult | jsocketpp::DatagramSocket::readExact (void *buffer, std::size_t exactLen, const ReadExactOptions &opts={}) const |
Receive exactly exactLen bytes from a single UDP datagram into buffer, with strict policy control. | |
| DatagramReadResult | jsocketpp::DatagramSocket::readExact (std::span< char > out, const ReadExactOptions &opts={}) const |
Span overload of readExact(...) (derives exactLen from out.size()). | |
| template<typename T> | |
| DatagramReadResult | jsocketpp::DatagramSocket::readExact (T &buffer, const std::size_t exactLen, const ReadExactOptions &opts={}) const |
Receive exactly exactLen bytes from a single UDP datagram into a contiguous byte container. | |
| std::size_t | jsocketpp::DatagramSocket::readAtMost (std::span< char > out, const DatagramReadOptions &opts={}) const |
Read up to out.size() bytes from the next UDP datagram into a caller-provided buffer (no allocation). | |
| std::string | jsocketpp::DatagramSocket::readAvailable () const |
| Receive the next UDP datagram and return its payload as a string, attempting to avoid truncation. | |
| std::size_t | jsocketpp::DatagramSocket::readAvailable (std::span< char > out, const DatagramReadOptions &opts={}) const |
| Receive the entire next UDP datagram into a caller-provided buffer, with explicit truncation policy. | |
| std::size_t | jsocketpp::DatagramSocket::readIntoExact (void *buffer, std::size_t len) const |
| Strict exact-length UDP receive into a caller-provided buffer (single datagram). | |
| std::string | jsocketpp::DatagramSocket::readAtMostWithTimeout (std::size_t n, int timeoutMillis) const |
Read up to n bytes from the next UDP datagram, waiting up to timeoutMillis for data. | |
| template<typename T, std::enable_if_t< std::is_integral_v< T > &&std::is_unsigned_v< T > &&std::is_trivially_copyable_v< T >, int > = 0> | |
| std::string | jsocketpp::DatagramSocket::readPrefixed (std::size_t maxPayloadLen=MaxDatagramPayloadSafe, const std::endian prefixEndian=std::endian::big) const |
Read a length-prefixed UDP datagram and return the payload (prefix type T). | |
| void | jsocketpp::DatagramSocket::discard (const DatagramReadOptions &opts={}) const |
| Discard the next UDP datagram without copying it out. | |
| void | jsocketpp::DatagramSocket::discardExact (std::size_t n, const DatagramReadOptions &opts={}) const |
Discard the next UDP datagram only if its payload size is exactly n bytes. | |
| DatagramReadResult | jsocketpp::DatagramSocket::readv (std::span< BufferView > buffers, const DatagramReadOptions &opts={}) const |
| Scatter-gather receive: read one UDP datagram into multiple non-contiguous buffers. | |
| DatagramReadResult | jsocketpp::DatagramSocket::readvAll (std::span< BufferView > buffers, const DatagramReadOptions &opts={}) const |
| Scatter-gather receive that guarantees the entire next datagram fits the provided buffers. | |
| std::size_t | jsocketpp::DatagramSocket::readvAllBytes (std::span< BufferView > buffers, const DatagramReadOptions &opts={}) const |
| Back-compat convenience returning only the number of bytes copied. | |
| DatagramReadResult | jsocketpp::DatagramSocket::readvAtMostWithTimeout (std::span< BufferView > buffers, int timeoutMillis, const DatagramReadOptions &opts={}) const |
| Scatter-gather, best-effort read of the next datagram with a per-call timeout. | |
| std::size_t | jsocketpp::DatagramSocket::readvAtMostWithTimeout (std::span< BufferView > buffers, int timeoutMillis) const |
| Convenience wrapper returning only the number of bytes read. | |
| DatagramReadResult | jsocketpp::DatagramSocket::readvAllWithTotalTimeout (std::span< BufferView > buffers, int totalTimeoutMillis, const DatagramReadOptions &opts={}) const |
| Scatter-gather, strict no-truncation receive with a per-call total timeout. | |
| std::size_t | jsocketpp::DatagramSocket::readvAllWithTotalTimeoutBytes (std::span< BufferView > buffers, int totalTimeoutMillis, const DatagramReadOptions &opts={}) const |
| Convenience wrapper returning only the number of bytes copied. | |
| DatagramReadResult | jsocketpp::DatagramSocket::peek (DatagramPacket &packet, bool allowResize=true, const DatagramReadOptions &opts={}) const |
| Peek at the next UDP datagram without consuming it (single receive with MSG_PEEK). | |
| bool | jsocketpp::DatagramSocket::hasPendingData (int timeoutMillis) const |
| Check if the socket is readable within a timeout (no data is consumed). | |
| std::optional< int > | jsocketpp::DatagramSocket::getMTU () const |
| Retrieves the Maximum Transmission Unit (MTU) of the local interface associated with the socket. | |
| void | jsocketpp::DatagramSocket::waitReady (Direction dir, int timeoutMillis) const |
| Block until the socket is ready for I/O or a timeout occurs. | |
| void | jsocketpp::DatagramSocket::setInternalBufferSize (std::size_t newLen) |
| Sets the size of the internal buffer used for string-based UDP receive operations. | |
| void | jsocketpp::DatagramSocket::close () |
| Closes the datagram socket and releases its underlying system resources. | |
| bool | jsocketpp::DatagramSocket::isValid () const noexcept |
| Checks whether the datagram socket is valid and ready for use. | |
| bool | jsocketpp::DatagramSocket::isClosed () const noexcept |
| Checks whether the datagram socket has been closed or is otherwise invalid. | |
| std::optional< std::pair< sockaddr_storage, socklen_t > > | jsocketpp::DatagramSocket::getLastPeerSockAddr () const |
| Retrieves the raw socket address of the last known remote peer. | |
| std::size_t | jsocketpp::DatagramSocket::readIntoBuffer (char *buf, std::size_t len, DatagramReceiveMode mode, int recvFlags, sockaddr_storage *outSrc, socklen_t *outSrcLen, std::size_t *outDatagramSz, bool *outTruncated) const |
| Low-level, single-recv primitive that copies one UDP datagram into a caller buffer. | |
| void | jsocketpp::DatagramSocket::cleanup () |
| Internal helper that releases socket resources and resets all internal state. | |
| void | jsocketpp::DatagramSocket::cleanupAndThrow (int errorCode) |
| Releases all socket resources and throws a SocketException with the given error code. | |
| void | jsocketpp::DatagramSocket::cleanupAndRethrow () |
| Cleans up the datagram socket and rethrows the currently active exception. | |
| std::size_t | jsocketpp::DatagramSocket::chooseReceiveSize () const |
| Decide how many bytes to attempt to receive for the next UDP datagram. | |
| static void | jsocketpp::DatagramSocket::throwSizeMismatch (const std::size_t expected, const std::size_t actual, const bool isProbedKnown) |
| Throw a descriptive exception when a UDP datagram’s size differs from what was expected. | |
| void | jsocketpp::DatagramSocket::enforceSendCapConnected (const std::size_t payloadSize) const |
| Enforce UDP payload size limits for connected datagram sends. | |
| void | jsocketpp::DatagramSocket::sendUnconnectedTo (std::string_view host, Port port, const void *data, std::size_t len) |
| Resolve and send one unconnected UDP datagram to the first compatible destination. | |
| static std::span< const std::byte > | jsocketpp::DatagramSocket::asBytes (const std::string_view sv) noexcept |
| View a textual buffer as raw bytes without copying. | |
| template<typename T> | |
| static std::array< std::byte, sizeof(T)> | jsocketpp::DatagramSocket::encodeLengthPrefixBE (std::size_t n) |
| Encode a length value into a fixed-size, big-endian (network-order) byte array. | |
| template<typename T> | |
| void | jsocketpp::DatagramSocket::sendPrefixedConnected (const std::span< const std::byte > payload) const |
| Build and send a length-prefixed UDP datagram to the connected peer (no pre-wait). | |
| template<typename T> | |
| void | jsocketpp::DatagramSocket::sendPrefixedUnconnected (const std::string_view host, const Port port, const std::span< const std::byte > payload) |
| Build and send a length-prefixed UDP datagram to (host, port) on the unconnected path. | |
| void | jsocketpp::DatagramSocket::cacheLocalEndpoint () noexcept |
| Cache the actual local endpoint assigned by the OS. | |
| bool | jsocketpp::DatagramSocket::tryGetRemoteSockaddr (sockaddr_storage &out, socklen_t &outLen) const |
| Retrieve the remote endpoint sockaddr for this socket, if available. | |
| jsocketpp::MulticastSocket::MulticastSocket (Port localPort, std::string_view localAddress, std::optional< std::size_t > recvBufferSize=std::nullopt, std::optional< std::size_t > sendBufferSize=std::nullopt, std::optional< std::size_t > internalBufferSize=std::nullopt, bool reuseAddress=true, int soRecvTimeoutMillis=-1, int soSendTimeoutMillis=-1, bool nonBlocking=false, bool dualStack=true, bool autoBind=true) | |
| Constructs a fully configurable multicast socket for receiving and sending datagrams. | |
| void | jsocketpp::MulticastSocket::joinGroup (const std::string &groupAddr, const std::string &iface) |
| Join a multicast group on an optional interface (string-friendly). | |
| void | jsocketpp::MulticastSocket::leaveGroup (const std::string &groupAddr, const std::string &iface="") |
| Leave a multicast group on an optional interface (string-friendly). | |
| void | jsocketpp::MulticastSocket::setMulticastInterface (const std::string &iface) |
| Select the default outgoing interface for multicast transmissions. | |
| std::string | jsocketpp::MulticastSocket::getMulticastInterface () const |
| Get the currently selected egress interface for multicast transmissions. | |
| void | jsocketpp::MulticastSocket::setTimeToLive (int ttl) |
| Set the time-to-live (TTL) / hop limit for outgoing multicast packets. | |
| void | jsocketpp::MulticastSocket::setLoopbackMode (bool enable) |
| Enable or disable multicast loopback for this socket. | |
| static in_addr | jsocketpp::MulticastSocket::resolveIPv4 (std::string_view host) |
| Resolve a host string to an IPv4 address (in_addr, network byte order). | |
| static in6_addr | jsocketpp::MulticastSocket::resolveIPv6 (std::string_view host) |
| Resolve a host string to an IPv6 address (in6_addr). | |
Classes and functions for UDP datagram networking.
|
strong |
Receive-time sizing policy for UDP datagrams.
Controls how DatagramSocket::read(...) chooses the number of bytes to request from the OS for the next UDP datagram. This affects both the likelihood of truncation and the number of syscalls performed per receive.
General behavior
Performance note
| Enumerator | |
|---|---|
| NoPreflight | Do not probe the datagram size; call recvfrom() directly.
Use this for fixed-size protocols or hot paths where every syscall counts. |
| PreflightSize | Probe the exact size of the next datagram and size the receive accordingly.
Choose this when datagram sizes vary widely and avoiding truncation is more important than minimizing syscalls. |
| PreflightMax | Probe the size of the next datagram but cap it at the current buffer length.
Use this to avoid oversizing reads while still skipping unnecessary extra bytes for smaller datagrams. |
|
strong |
I/O readiness selector used by waitReady().
Specifies which readiness condition to wait for on a datagram socket when calling waitReady(). On POSIX systems this corresponds to polling for POLLIN (readable) and/or POLLOUT (writable). On Windows, it maps to POLLRDNORM and/or POLLWRNORM via WSAPoll. For UDP sockets:
|
inlinestaticprotectednoexcept |
View a textual buffer as raw bytes without copying.
Returns a std::span<const std::byte> that references the same memory as the input std::string_view sv. This is an O(1), zero-allocation conversion intended for APIs that operate on binary payloads (e.g., UDP datagram sends) while callers may naturally hold data as text.
sv. Callers must ensure that storage remains alive until any I/O using the span completes.| [in] | sv | The textual data to re-interpret as bytes. May be empty. |
sv (possibly empty).| void DatagramSocket::bind | ( | ) |
Binds the datagram socket to all available interfaces on an ephemeral port.
This method binds the DatagramSocket to an ephemeral (auto-assigned) local port on all local network interfaces (0.0.0.0 for IPv4 or :: for IPv6), depending on system configuration and address resolution.
| SocketException | if address resolution or binding fails. |
| void DatagramSocket::bind | ( | Port | localPort | ) |
Binds the datagram socket to a specific local port on all network interfaces.
This overload binds the socket to the given UDP localPort across all available network interfaces, using a wildcard address (0.0.0.0 for IPv4 or :: for IPv6).
| [in] | localPort | UDP port number to bind to. Must be in the range [1, 65535], or 0 to request an ephemeral port. |
| SocketException | if address resolution or binding fails, or if the socket is already bound. |
| void DatagramSocket::bind | ( | std::string_view | localAddress, |
| Port | localPort ) |
Binds the datagram socket to a specific local IP address and port.
This method allows full control over the local binding interface by specifying both the local IP address (host) and port. It supports IPv4 and IPv6 addresses, including loopback, multicast-capable interfaces, and link-local addresses.
| [in] | localAddress | Local IP address or hostname to bind to (e.g., "127.0.0.1", "::1", "eth0.local"). Use "0.0.0.0" or "::" to bind to all interfaces (same as bind(port)). |
| [in] | localPort | Local UDP port number to bind to. Use 0 for ephemeral port assignment. |
| SocketException | if address resolution or binding fails. |
|
inlineprotectednoexcept |
Cache the actual local endpoint assigned by the OS.
Invokes getsockname() on the socket and stores the result in _localAddr/_localAddrLen, setting _haveLocalAddr to true on success. Call this immediately after a successful bind() or after a UDP connect() that implicitly binds an ephemeral port. If getsockname() fails, the existing cached values are left unchanged.
@thread_safety Intended for the owning thread of the socket. Not synchronized against concurrent close(); coordinate externally if those may race.
| None. | This function is noexcept and never throws. |
|
inlineprotected |
Decide how many bytes to attempt to receive for the next UDP datagram.
This method centralizes the library’s Java-like sizing policy so all UDP read() variants behave consistently while keeping _internalBuffer as reusable storage only (never resized here).
Policy order:
Semantics:
|
protected |
Internal helper that releases socket resources and resets all internal state.
This method safely resets the DatagramSocket to an uninitialized state. It is used during error recovery to release partially constructed socket state, and ensures the object no longer appears bound or connected after failure.
|
protected |
Cleans up the datagram socket and rethrows the currently active exception.
This method is intended to be used inside a catch block when an exception occurs during socket construction or setup. It ensures all internal resources are safely released before rethrowing the original exception, leaving the socket in an uninitialized and safe state.
Internally calls cleanup(), which:
Then rethrows the active exception using throw;.
| SocketException | or the original active exception |
|
protected |
Releases all socket resources and throws a SocketException with the given error code.
This method performs complete internal cleanup of the datagram socket and then throws a SocketException. It is typically invoked when construction, binding, or configuration of the socket fails, ensuring the object is left in a safe, uninitialized state.
Internally delegates to cleanup(), which:
After cleanup, throws a SocketException with:
| [in] | errorCode | The system or application-level error code to report. |
| SocketException | Always throws after cleanup. |
| void DatagramSocket::close | ( | ) |
Closes the datagram socket and releases its underlying system resources.
This method performs a full teardown of the datagram socket, closing the underlying file descriptor/handle and releasing all associated resources. After closure, the socket becomes invalid and cannot be reused.
| SocketException | If the underlying close operation fails unexpectedly. |
| void DatagramSocket::connect | ( | std::string_view | host, |
| Port | port, | ||
| int | timeoutMillis ) |
Connect this UDP socket to a default peer (set the default destination).
Establishes a default remote endpoint for the datagram socket. After a successful call, send/receive operations that use the connected variants (e.g., send, recv) no longer require an explicit destination address. Unlike TCP, UDP "connect" performs no handshake; it simply sets the default peer and may implicitly bind the local endpoint (address/port).
This implementation:
host + port to a linked list of address candidates (IPv6 and/or IPv4).timeoutMillis ≥ 0, temporarily switches the socket to non-blocking mode and uses select() to wait for writability, respecting a single overall timeout budget across all candidates (not per-candidate).| [in] | host | Remote hostname or IP literal (IPv4/IPv6). |
| [in] | port | Remote UDP port. |
| [in] | timeoutMillis | Connection timeout in milliseconds. If < 0, the call is blocking. If 0, the function attempts a non-blocking connect and will time out immediately unless completion is instantaneous. |
| SocketException |
|
| SocketTimeoutException |
|
timeoutMillis.timeoutMillis ≥ 0 and getSocketFd() >= FD_SETSIZE, select() cannot be used and this function throws a SocketException before attempting the connection.
|
delete |
Copy constructor (deleted) for DatagramSocket.
The copy constructor is explicitly deleted to prevent copying of DatagramSocket instances. This class wraps a native socket file descriptor (SOCKET) and manages system-level resources that cannot be safely or meaningfully duplicated.
Copying would result in multiple objects referring to the same underlying socket, which would violate ownership semantics and could lead to:
Instead, use move semantics to transfer ownership safely between instances.
|
inlinenoexcept |
Move constructor for DatagramSocket.
Transfers ownership of the underlying socket file descriptor and internal state from another DatagramSocket instance. After the move, the source object is left in a valid but unspecified state and should not be used.
|
explicit |
Creates a UDP socket, optionally binds to a local address, and optionally connects to a remote peer.
This constructor supports both server-style and client-style UDP sockets:
The socket supports:
Bound UDP Server Useful for listening on a specific port/interface for datagrams from any peer.
Connected UDP Client Binds (optional) and then connects to a fixed remote peer. Enables write() / read(), ICMP error propagation, and performance improvements.
| [in] | localPort | The local port to bind from. Use 0 for ephemeral. |
| [in] | localAddress | The local IP to bind from (e.g., "192.168.1.100" or "::"). Empty for wildcard. |
| [in] | recvBufferSize | Optional socket receive buffer size (SO_RCVBUF) |
| [in] | sendBufferSize | Optional socket send buffer size (SO_SNDBUF) |
| [in] | internalBufferSize | Optional internal buffer size used by high-level read methods |
| [in] | reuseAddress | If true, enables SO_REUSEADDR to allow rebinding the port |
| [in] | soRecvTimeoutMillis | Timeout for receive operations in milliseconds (-1 disables) |
| [in] | soSendTimeoutMillis | Timeout for send operations in milliseconds (-1 disables) |
| [in] | nonBlocking | If true, sets the socket to non-blocking mode immediately |
| [in] | dualStack | If true, enables IPv6 sockets to accept IPv4-mapped addresses |
| [in] | autoBind | If true, performs a bind() using localAddress and localPort after construction |
| [in] | autoConnect | If true, immediately connects to the remote peer using remoteAddress and remotePort |
| [in] | remoteAddress | The remote host/IP to connect to (used only if autoConnect == true) |
| [in] | remotePort | The remote UDP port to connect to (used only if autoConnect == true) |
| [in] | connectTimeoutMillis | Timeout (in ms) for the connection attempt when autoConnect == true:
|
| SocketException | If any step of socket resolution, creation, binding, configuration, or connection fails |
| SocketTimeoutException | If the connect() call exceeds the specified connectTimeoutMillis timeout |
| void DatagramSocket::discard | ( | const DatagramReadOptions & | opts = {} | ) | const |
Discard the next UDP datagram without copying it out.
Consumes exactly one datagram from the socket and discards its bytes. This method ignores the datagram size and never throws due to truncation. Timeouts and OS-level receive errors still apply. On unconnected sockets, when opts.updateLastRemote is true, the internally tracked “last remote” endpoint is updated to the sender of the discarded datagram.
| [in] | opts | Read options controlling sender bookkeeping and receive flags. The mode field is ignored (a single receive is always performed). Truncation reporting is ignored. |
| SocketException | If the socket is not open or an OS-level receive error occurs (message via SocketErrorMessage). |
| SocketTimeoutException | If a configured receive timeout elapses before any datagram is available, or when the socket is non-blocking and no data is available (would-block). |
opts.updateLastRemote is true, the internal “last remote” reflects that sender.| void DatagramSocket::discardExact | ( | std::size_t | n, |
| const DatagramReadOptions & | opts = {} ) const |
Discard the next UDP datagram only if its payload size is exactly n bytes.
Enforces exact-length semantics while draining the datagram:
n and throws before reading when it does not, so the datagram remains queued.n bytes. If the datagram is larger than n, the kernel truncates it; this method then throws. If the datagram is smaller than n, it also throws. In other words, the datagram must be exactly n bytes or the call fails.The discard operation minimizes copying: when the size is known to be n, the method reads with a tiny scratch buffer to consume the datagram (the kernel drops the remainder).
On unconnected sockets, when opts.updateLastRemote is true, the internally tracked “last remote” endpoint is updated to the sender of the discarded datagram.
| [in] | n | Required datagram payload size (> 0). |
| [in] | opts | Read options controlling sender bookkeeping and receive flags. Truncation policy in opts is ignored; this method enforces its own exact-length checks. |
| SocketException | If the socket is not open; n == 0; OS-level receive errors occur (message via SocketErrorMessage); or the next datagram’s size is not exactly n bytes. |
| SocketTimeoutException | If a configured receive timeout elapses before any datagram is available, or when the socket is non-blocking and no data is available (would-block). |
n > 0. n. For unconnected sockets, when opts.updateLastRemote is true, the internal “last remote” reflects that sender.| void DatagramSocket::disconnect | ( | ) |
Disconnect this UDP socket from its current default peer.
Dissolves the association set by a prior connect() without closing the socket. Internally, this issues ::connect(fd, { .sa_family = AF_UNSPEC }, sizeof(sockaddr)), which is the standard UDP “disconnect” idiom on POSIX and Winsock. The socket remains open and (if previously bound) stays bound to its local address/port; only the default remote peer is cleared.
This implementation:
| SocketException | If the socket is not open, or if the underlying connect(AF_UNSPEC) fails. The exception carries GetSocketError() and SocketErrorMessage(GetSocketError()). |
|
inlinestaticprotected |
Encode a length value into a fixed-size, big-endian (network-order) byte array.
| T | Unsigned integral type used for the length prefix. Typical choices are std::uint8_t, std::uint16_t, std::uint32_t, or std::uint64_t. A compile-time check enforces that T is an unsigned integral. |
Converts n into its big-endian (network byte order) representation using exactly sizeof(T) bytes and returns the result as std::array<std::byte, sizeof(T)>. The function is O(sizeof(T)) and allocation-free.
n are representable; values that do not fit are rejected with a logical exception (see Throws).This helper is intended for building length-prefixed UDP frames with a prefix followed by payload bytes, where the prefix must be in network byte order for interoperability.
| [in] | n | The length value to encode. Must satisfy n <= std::numeric_limits<T>::max(). |
n encoded in big-endian order.| SocketException |
|
|
inlineprotected |
Enforce UDP payload size limits for connected datagram sends.
Validates that a single datagram of payloadSize bytes can be sent to the currently connected peer without exceeding protocol-level maxima.
The check is conservative by default:
If the socket is connected to IPv4 (AF_INET) and payloadSize exceeds the IPv4 limit (MaxUdpPayloadIPv4 = 65,507), an exception is thrown before calling send(), providing a precise, user-friendly error message.
The remote address family is determined via: 1) cached last-peer address when available, otherwise 2) a getpeername() query on the connected socket.
Proactive validation yields deterministic, actionable errors (instead of a vague EMSGSIZE from the kernel) and avoids futile syscalls.
| [in] | payloadSize | Number of bytes intended for a single datagram. |
| SocketException |
|
|
inlinenodiscard |
Retrieves the raw socket address of the last known remote peer.
This method exposes the internal low-level sockaddr_storage structure representing the last known remote peer that this socket communicated with. It is useful in advanced use cases where direct access to address structures is required — for example:
|
nodiscard |
Return the local interface IP address for this UDP socket.
Returns the textual IP address (IPv4 or IPv6) currently bound to this socket. If a cached local endpoint is available, it is used without a syscall. Otherwise, this method performs a single getsockname() and, on success, updates the internal cache (only if the kernel reports a non-zero port, i.e., the socket is actually bound). This method is non-const because it may refresh and persist the cached local endpoint.
When convertIPv4Mapped is true and the underlying address is an IPv6 IPv4-mapped address (::ffff:a.b.c.d), the returned string is converted to an IPv4 literal (a.b.c.d). For IPv6 link-local addresses, the scope ID may be included if available (e.g., fe80::1eth0), depending on platform conventions and the socket's bound interface.
| [in] | convertIPv4Mapped | If true, convert IPv4-mapped IPv6 addresses to IPv4 text form; if false, return the canonical address text as reported by the OS. |
| SocketException |
|
|
nodiscard |
Return the local UDP port this socket is bound to.
Returns the numeric port currently bound to this socket. If a cached local endpoint is available, it is used without a syscall. Otherwise, this method performs a single getsockname() and, on success, updates the internal cache only if the kernel reports a non-zero port (i.e., the socket is actually bound). This method is non-const because it may refresh and persist the cached local endpoint.
| SocketException |
|
|
nodiscard |
Return the local endpoint as a single "ip:port" string.
Builds a presentation string for the socket’s current local endpoint by combining the local IP and port. If a cached local endpoint is available, it is used without a syscall. Otherwise, this method performs a single getsockname() and, on success, updates the internal cache only if the kernel reports a non-zero port (i.e., the socket is actually bound). This method is non-const because it may refresh and persist the cached local endpoint. For IPv6 addresses, the IP may be bracketed (e.g., [2001:db8::1]:54321) depending on the formatting used by the underlying helpers.
When convertIPv4Mapped is true and the underlying address is an IPv6 IPv4-mapped address (::ffff:a.b.c.d), the IP portion is converted to an IPv4 literal (a.b.c.d) before concatenation.
| [in] | convertIPv4Mapped | If true, convert IPv4-mapped IPv6 addresses to IPv4 text form in the result. |
| SocketException |
|
|
nodiscard |
Retrieves the Maximum Transmission Unit (MTU) of the local interface associated with the socket.
This method attempts to query the MTU of the network interface to which the socket is currently bound. It supports both Windows and POSIX platforms using appropriate system APIs and returns the result as an optional integer.
The MTU is the largest size (in bytes) of a datagram that can be sent over a network interface without fragmentation. For example, Ethernet IPv4 commonly uses an MTU of 1500 bytes, while the payload limit for UDP is typically 1472 bytes after IP/UDP headers.
| SocketException | If a low-level socket operation (e.g., getsockname()) fails. |
|
inlinenodiscard |
Get the currently selected egress interface for multicast transmissions.
Returns the human-friendly identifier that this object currently holds as the default outgoing multicast interface, as last set via setMulticastInterface(const std::string&). This is a cached value intended for diagnostics and UI; it does not perform a fresh system query.
Possible return forms (depending on how the interface was selected):
|
nodiscard |
Return the remote peer IP address for this socket.
Produces the textual IP address (IPv4 or IPv6) of the current remote endpoint. The source of truth is:
When convertIPv4Mapped is true and the address is IPv6 IPv4-mapped (::ffff:a.b.c.d), the result is converted to an IPv4 literal (a.b.c.d).
| [in] | convertIPv4Mapped | Convert IPv4-mapped IPv6 addresses to IPv4 text if true. |
| SocketException |
|
|
nodiscard |
Return the remote peer UDP port for this socket.
Obtains the numeric port of the current remote endpoint. The source of truth is:
| SocketException |
|
|
nodiscard |
Return the remote endpoint as a single "ip:port" string.
Formats the current remote endpoint into a presentation string. The source of truth is:
When convertIPv4Mapped is true and the address is an IPv6 IPv4-mapped form (::ffff:a.b.c.d), the IP portion is converted to an IPv4 literal (a.b.c.d) before concatenation. If your IP formatter brackets IPv6 addresses, the result may look like "[2001:db8::1]:5353".
| [in] | convertIPv4Mapped | If true, convert IPv4-mapped IPv6 addresses to IPv4 text before building the result. |
| SocketException |
|
|
inlinenodiscardnoexcept |
Report whether this packet specifies an explicit destination (address + port).
Returns true if the packet’s destination fields are set to a usable value for sending: a non-blank address (not just whitespace) and a non-zero UDP port. This is a syntactic check only; it does not validate that the address string is a resolvable host/IP or that the port is reachable.
Typical uses:
| bool DatagramSocket::hasPendingData | ( | int | timeoutMillis | ) | const |
Check if the socket is readable within a timeout (no data is consumed).
Waits until the socket becomes readable and returns whether at least one datagram is ready to be received. This call does not read or consume data; it only checks readiness. A negative timeoutMillis blocks indefinitely. A zero timeout performs a non-blocking poll.
Implementation uses poll on POSIX and WSAPoll on Windows (preferred over select to avoid FD_SETSIZE limits and provide better EINTR semantics).
| [in] | timeoutMillis | Timeout in milliseconds. < 0 = infinite, 0 = immediate, > 0 = bounded wait. |
| SocketException | If the socket is not open or if the readiness API reports an error (error code/message via SocketErrorMessage). |
|
inlinenodiscardnoexcept |
Indicates whether the datagram socket has been explicitly bound to a local address or port.
Returns true if the socket has successfully completed a call to one of the bind() overloads. Binding is optional for UDP sockets, but is commonly required for:
|
inlinenodiscardnoexcept |
Checks whether the datagram socket has been closed or is otherwise invalid.
Returns true if the socket is no longer usable—either because it was explicitly closed via close(), or because it was never successfully initialized (i.e., holds an invalid file descriptor).
This method does not perform any system-level query. It simply checks whether the internal socket descriptor equals INVALID_SOCKET. This is the standard invariant for resource management in the jsocketpp UDP API.
|
inlinenodiscardnoexcept |
Indicates whether the datagram socket is connected to a specific remote peer.
Returns true if the socket has been successfully connected to a remote address and port using the connect() method. While UDP is a connectionless protocol, invoking connect() on a datagram socket enables connection-oriented semantics:
|
inlinenodiscardnoexcept |
Checks whether the datagram socket is valid and ready for use.
Returns true if the socket has a valid file descriptor and has not been closed or moved-from. A valid datagram socket can be used for sending and receiving UDP packets, though it may or may not be bound or connected.
This method performs a quick, local check:
| void MulticastSocket::joinGroup | ( | const std::string & | groupAddr, |
| const std::string & | iface ) |
Join a multicast group on an optional interface (string-friendly).
Adds this socket to the multicast group identified by groupAddr, optionally scoping the membership to a specific local interface indicated by iface. The method accepts human-friendly identifiers and performs resolution and validation before delegating to the OS via setsockopt.
Accepted forms
groupAddr: iface (optional selector of the local interface used for membership):Behavior
groupAddr to either in_addr or in6_addr (IPv4/IPv6), using a fast literal path first, then the project resolver (resolveAddress(...)).iface as described above and binds the membership to that interface.Notes
iface in that case.| [in] | groupAddr | Multicast group (literal or resolvable name), IPv4 or IPv6. |
| [in] | iface | Optional interface selector as described above; empty uses the default. |
| SocketException |
|
| void MulticastSocket::leaveGroup | ( | const std::string & | groupAddr, |
| const std::string & | iface = "" ) |
Leave a multicast group on an optional interface (string-friendly).
Removes this socket’s membership from the multicast group identified by groupAddr. The interface used for the leave operation can be selected via iface and follows the same conventions as joinGroup.
Accepted forms
groupAddr: iface (optional; selects the local interface whose membership is removed):Behavior
groupAddr to either an in_addr or in6_addr via a fast literal path first, and otherwise through the project resolver (resolveAddress).iface as described above to obtain the IPv4 interface address or IPv6 interface index used when the membership was created.Notes
| [in] | groupAddr | Multicast group to leave (literal or resolvable name), IPv4 or IPv6. |
| [in] | iface | Optional interface selector as described above; default is the empty string, which uses the system default (IPv4 INADDR_ANY, IPv6 index 0). |
| SocketException |
|
| MulticastSocket::MulticastSocket | ( | Port | localPort, |
| std::string_view | localAddress, | ||
| std::optional< std::size_t > | recvBufferSize = std::nullopt, | ||
| std::optional< std::size_t > | sendBufferSize = std::nullopt, | ||
| std::optional< std::size_t > | internalBufferSize = std::nullopt, | ||
| bool | reuseAddress = true, | ||
| int | soRecvTimeoutMillis = -1, | ||
| int | soSendTimeoutMillis = -1, | ||
| bool | nonBlocking = false, | ||
| bool | dualStack = true, | ||
| bool | autoBind = true ) |
Constructs a fully configurable multicast socket for receiving and sending datagrams.
This advanced constructor provides complete control over the configuration of a multicast UDP socket, including binding behavior, buffer sizes, timeouts, and dual-stack support. It is designed for power users who need fine-grained socket tuning prior to joining one or more multicast groups using joinGroup().
Unlike simpler constructors, this overload supports use cases such as:
No multicast group is joined automatically — you must call joinGroup() after construction.
| [in] | localPort | The local port to bind to. Use 0 to request an ephemeral port assigned by the OS. |
| [in] | localAddress | Optional local interface or IP address to bind to. Common values:
|
| [in] | recvBufferSize | Optional size of the OS-level receive buffer, in bytes (e.g., 4096). If std::nullopt, the default size is used. |
| [in] | sendBufferSize | Optional size of the OS-level send buffer, in bytes. If std::nullopt, the default is used. |
| [in] | internalBufferSize | Optional size of the internal user-space buffer used by read() and related methods. |
| [in] | reuseAddress | Whether to enable SO_REUSEADDR so multiple sockets can bind to the same port (useful for multiple receivers on the same machine). |
| [in] | soRecvTimeoutMillis | Receive timeout in milliseconds. Use -1 to disable. |
| [in] | soSendTimeoutMillis | Send timeout in milliseconds. Use -1 to disable. |
| [in] | nonBlocking | If true, the socket is set to non-blocking mode after creation. |
| [in] | dualStack | Enables IPv4-mapped IPv6 support when using "::" bind addresses. Has no effect for IPv4-only sockets. |
| [in] | autoBind | If true, the socket will automatically call bind() to the given address and port. If false, you must call bind() manually before using the socket. |
| SocketException | If socket creation, binding, or option setting fails for any reason. |
|
delete |
Copy assignment operator (deleted) for DatagramSocket.
The copy assignment operator is explicitly deleted to prevent assignment between DatagramSocket instances. This class manages a native socket file descriptor and internal buffers, which must have clear ownership semantics.
Allowing copy assignment would result in:
This deletion enforces safe, move-only usage patterns consistent across the socket library.
|
inlinenoexcept |
Move assignment operator for DatagramSocket.
Releases any resources owned by this socket instance and transfers ownership from another DatagramSocket object (rhs). After the operation:
| [in,out] | rhs | The source DatagramSocket to move from. |
|
nodiscard |
Peek at the next UDP datagram without consuming it (single receive with MSG_PEEK).
Copies up to packet.buffer.size() bytes from the next datagram into packet.buffer using a single kernel receive with MSG_PEEK so the datagram remains queued. The method:
packet.buffer before peeking when allowResize is true: it first tries to probe the next datagram size and, if successful, resizes exactly to that size (clamped to MaxDatagramPayloadSafe); otherwise it uses a safe default.On POSIX, uses recvmsg with MSG_PEEK; on Linux it also sets MSG_TRUNC so the return value reflects the full datagram size even when the user buffer is smaller. On Windows, uses recvfrom with MSG_PEEK.
| [in,out] | packet | Destination DatagramPacket. Its buffer is the peek target; when allowResize is true and the size is known, it may be resized prior to the peek. When opts.resolveNumeric is true, packet.address and packet.port are filled. |
| [in] | allowResize | When true and a size probe succeeds, grow packet.buffer to fit exactly (clamped to MaxDatagramPayloadSafe). If false and the buffer is empty, the call throws. |
| [in] | opts | Read options. resolveNumeric is honored; recvFlags is OR’ed with MSG_PEEK. Other fields (e.g., updateLastRemote) are ignored for peek (no side-effects). |
| SocketException | If the socket is not open; packet.buffer is empty and allowResize is false; OS-level errors occur (message via SocketErrorMessage). |
| SocketTimeoutException | If the socket is non-blocking and no data is available (would-block), or a configured receive timeout elapses (platform-mapped). |
|
inlinenodiscard |
Read one UDP datagram into a fixed-size, contiguous byte container (zero allocation).
| T | A fixed-size, contiguous byte-like container (e.g., std::array<char, N>, std::array<unsigned char, N>, std::array<std::byte, N>) exposing data() and size(). |
Performs exactly one receive and copies up to T::size() bytes into the returned container. Trailing bytes remain value-initialized (typically zero) if the datagram is shorter. Truncation behavior is controlled by opts.errorOnTruncate:
opts.errorOnTruncate is true, the function throws before reading so the datagram stays queued.opts.errorOnTruncate is true, it throws after the read.opts.errorOnTruncate is false, the payload is truncated to T::size() without error. When opts.updateLastRemote is true, the internally tracked “last remote” is updated. The requested copy length is always clamped to MaxDatagramPayloadSafe.| [in] | opts | Read options controlling preflight, truncation policy, and sender bookkeeping. |
T containing the received bytes in its leading elements. Any unused tail remains value-initialized.| SocketException | If the socket is not open, on OS-level errors (message via SocketErrorMessage), or when truncation is disallowed by opts.errorOnTruncate. |
| SocketTimeoutException | If a receive timeout elapses before any datagram is available, or when the socket is non-blocking and no data is available. |
n bytes of the returned container hold the payload, where n ≤ T::size(). If opts.updateLastRemote is true, the internal “last remote” reflects the sender.opts.errorOnTruncate = true with DatagramReceiveMode::PreflightSize for strict no-truncation behavior when supported by the platform.
|
inlinenodiscard |
Read one UDP datagram into a dynamically resizable, contiguous byte container (zero-copy into caller storage).
| T | A contiguous, dynamically resizable byte-like container (e.g., std::string, std::vector<char>, std::vector<std::byte>, std::pmr::string) that provides data(), size(), and resize(). |
Allocates a buffer in T, receives exactly one datagram into it, and then shrinks the container to the number of bytes actually received. Capacity is chosen as follows:
minCapacity, clamped to MaxDatagramPayloadSafe. If minCapacity is 0, it is treated as 1 to allow clean reception of zero-length datagrams.The actual copy is performed with a single kernel receive via readInto(...). If truncation occurs and opts.errorOnTruncate == true, readInto(...) will throw according to its policy (either before the read, when size is known, or after the read otherwise). On success, the container is shrunk to the number of bytes received. No null terminator is appended automatically.
| [in] | opts | Read options (preflight mode, truncation policy, sender bookkeeping). |
| [in] | minCapacity | Minimum initial capacity to allocate before reading. Clamped to MaxDatagramPayloadSafe. |
T holding the received payload (size equals the number of bytes received).| SocketException | If the socket is not open, OS-level errors occur (message via SocketErrorMessage), or truncation is disallowed by opts.errorOnTruncate and would occur. |
| SocketTimeoutException | If a configured receive timeout elapses before any datagram is received, or when the socket is non-blocking and no data is available (would-block). |
| DatagramReadResult DatagramSocket::read | ( | DatagramPacket & | packet, |
| const DatagramReadOptions & | opts ) const |
Read one UDP datagram into a DatagramPacket with optional growth/shrink and strict truncation policy.
Receives exactly one datagram and copies its payload into packet.buffer. Behavior is governed by opts:
opts.allowGrow is true, the buffer may be resized up front (clamped to MaxDatagramPayloadSafe) to fit the datagram exactly.opts.errorOnTruncate is true, the call throws before reading when size is known; otherwise it throws after the read if truncation occurred.opts.allowShrink is true and no truncation occurred, the buffer may be resized down to the exact number of bytes received.opts.updateLastRemote is true, the internally tracked “last remote” is updated to the sender.opts.resolveNumeric is true, packet.address and packet.port are filled with the sender’s numeric host and port. Exactly one kernel receive is performed for the payload copy; all requests are clamped to MaxDatagramPayloadSafe.opts.errorOnTruncate is true, the method fails early without consuming the datagram. The actual copy is performed with a single recv/recvmsg call via the internal backbone.| [in,out] | packet | Destination datagram container. On input, its buffer capacity limits the copy unless opts.allowGrow enables pre-read resizing. On success, the first result.bytes bytes contain the payload; address/port fields are updated when requested. |
| [in] | opts | Read options controlling preflight, capacity growth/shrink, truncation policy, sender bookkeeping, and numeric address resolution. |
bytes Number of bytes copied into packet.buffer.datagramSize Full datagram size when known (0 if unknown on this platform/path).truncated True if the datagram did not fully fit the destination buffer.| SocketException | If the socket is not open, arguments are invalid, OS-level receive errors occur (message via SocketErrorMessage), or truncation is disallowed by opts.errorOnTruncate. |
| SocketTimeoutException | If a configured receive timeout elapses before any datagram is received, or when the socket is non-blocking and no data is available. |
packet.buffer holds the received payload (possibly resized per opts.allowShrink). When opts.updateLastRemote is true, the internal “last remote” reflects the sender.opts.errorOnTruncate is false, oversized datagrams are truncated by the kernel and the tail is lost. Enable opts.errorOnTruncate for strict no-truncation behavior.| std::size_t DatagramSocket::readAtMost | ( | std::span< char > | out, |
| const DatagramReadOptions & | opts = {} ) const |
Read up to out.size() bytes from the next UDP datagram into a caller-provided buffer (no allocation).
Performs exactly one receive with at-most semantics:
out, only that many bytes are written.out, only the first out.size() bytes are written and the remainder of the datagram is discarded by the kernel (standard UDP truncation).This API enforces a single recv(from) with no extra syscalls by using DatagramReceiveMode::NoPreflight for the actual receive (any opts.mode setting is overridden for this method). On unconnected sockets, when opts.updateLastRemote == true, the internally tracked “last remote” endpoint is updated to the sender.
Blocking/timeout behavior:
| [out] | out | Destination span receiving at most out.size() bytes. |
| [in] | opts | Read options; fields other than mode are honored. The effective mode is forced to DatagramReceiveMode::NoPreflight to preserve single-recv semantics. |
out (0 if out is empty).| SocketException | If the socket is not open, on argument errors, or on other OS-level receive errors (message via SocketErrorMessage). |
| SocketTimeoutException | If a configured receive timeout elapses before any datagram is received, or when the socket is non-blocking and no data is available. |
out. For unconnected sockets, when opts.updateLastRemote == true, the internal “last remote” reflects the sender of this datagram.out is smaller than the datagram, the tail of that datagram is dropped (cannot be recovered).
|
nodiscard |
Read up to n bytes from the next UDP datagram, waiting up to timeoutMillis for data.
Blocks the caller for at most timeoutMillis milliseconds until the socket is readable, then performs a single-recv, best-effort read (no size preflight), returning up to n bytes. If no datagram arrives before the timeout, a SocketTimeoutException is thrown.
Implementation notes:
| [in] | n | Maximum number of bytes to return. If 0, returns an empty string. |
| [in] | timeoutMillis | Timeout in milliseconds. Must be >= 0. A value of 0 performs a non-blocking check and throws SocketTimeoutException if no data is ready. |
n). Marked [[nodiscard]] to avoid accidental loss.| SocketException | If the socket is not open or an OS-level error occurs while waiting/receiving (message via SocketErrorMessage). |
| SocketTimeoutException | If no datagram becomes available within timeoutMillis, or if the socket is non-blocking and no data is available at the moment of the call. |
timeoutMillis ≥ 0. n bytes from exactly one datagram; for unconnected sockets, the internal “last remote” reflects that datagram’s sender.
|
nodiscard |
Receive the next UDP datagram and return its payload as a string, attempting to avoid truncation.
Tries to return the entire next datagram:
On unconnected sockets, the internally tracked “last remote” endpoint is updated to the sender. This convenience overload forces a single-recv path and does not throw on truncation in the rare fallback case (truncation is accepted and the received bytes are returned).
Blocking/timeout behavior:
| SocketException | On socket not open or other OS-level receive errors (message via SocketErrorMessage). |
| SocketTimeoutException | If a receive timeout elapses before any datagram is received, or when the socket is non-blocking and no data is available. |
| std::size_t DatagramSocket::readAvailable | ( | std::span< char > | out, |
| const DatagramReadOptions & | opts = {} ) const |
Receive the entire next UDP datagram into a caller-provided buffer, with explicit truncation policy.
Attempts to copy the full datagram into out in a single receive:
out is smaller, it throws before reading (datagram remains queued).out and:On unconnected sockets, when opts.updateLastRemote == true, the internally tracked “last remote” endpoint is updated to the sender of this datagram.
Blocking/timeout behavior:
| [out] | out | Destination span that will receive up to out.size() bytes. |
| [in] | opts | Read options controlling size preflight, truncation policy, sender bookkeeping, and receive flags. Other fields are honored; this method may override the internal mode to avoid redundant preflight after a successful probe. |
out. Equals the datagram size when not truncated.| SocketException | If the socket is not open; on OS-level receive errors (message via SocketErrorMessage); or when out is too small and truncation is disallowed by opts.errorOnTruncate. |
| SocketTimeoutException | If a receive timeout elapses before any datagram is available, or when the socket is non-blocking and no data is available. |
out. For unconnected sockets, when opts.updateLastRemote == true, the internal “last remote” reflects the sender.out is smaller than the datagram and truncation is allowed, the remainder of that datagram is irretrievably dropped by the kernel per UDP semantics.
|
nodiscard |
Span overload of readExact(...) (derives exactLen from out.size()).
| [out] | out | [out] Destination span; on success, exactly out.size() bytes are written. |
| [in] | opts | [in] Exact-read policy and base receive options. |
|
inlinenodiscard |
Receive exactly exactLen bytes from a single UDP datagram into a contiguous byte container.
| T | A contiguous byte-like container with data() and size(). Supported: dynamic (e.g., std::string, std::vector<char/unsigned char/std::byte>) and fixed-size (e.g., std::array<char/unsigned char/std::byte, N>). |
Enforces exact-length semantics on top of a single datagram receive, governed by opts:
exactLen. If the datagram is smaller and opts.padIfSmaller == true, the read proceeds and the tail is zero-padded after copying.exactLen and opts.requireExact == true, the call throws after the read (the kernel truncated the payload). If the datagram is smaller than exactLen and opts.padIfSmaller == true, the tail is zero-padded; otherwise the call throws due to size mismatch.exactLen up front (after validating exactLen <= MaxDatagramPayloadSafe).exactLen (new bytes are value-initialized).Internally delegates to the pointer/span readExact(...) overload, which performs at most one kernel receive, attempts early failure via a size probe, applies zero-padding when requested, updates “last remote” per options, and returns a DatagramReadResult.
| [in,out] | buffer | Destination container. Must be contiguous and byte-sized. |
| [in] | exactLen | Required logical length (> 0). |
| [in] | opts | Exact-read policy (requireExact, padIfSmaller, autoResizeDynamic) and base options. |
exactLen; equals exactLen when padded or exact).exactLen and the kernel truncated the payload.| SocketException | If the socket is not open; arguments are invalid; exactLen exceeds MaxDatagramPayloadSafe (when auto-resizing); the dynamic container is too small and auto-resize is disabled; OS receive errors occur (message via SocketErrorMessage); or size policy fails (e.g., requireExact mismatch). |
| SocketTimeoutException | If a receive timeout elapses before any datagram is available, or in non-blocking mode with no data. |
exactLen > 0. For fixed-size containers, T::size() >= exactLen. buffer contains exactly exactLen bytes of payload (plus zero-padding when applicable).
|
nodiscard |
Receive exactly exactLen bytes from a single UDP datagram into buffer, with strict policy control.
Attempts to ensure the caller ends up with exactly exactLen bytes in buffer from the next datagram:
exactLen. If the datagram is smaller and opts.padIfSmaller == true, the read proceeds and the tail is zero-padded after copying.exactLen and opts.requireExact == true, the call throws after the read (the kernel truncated the payload). If the datagram is smaller than exactLen and opts.padIfSmaller == true, the tail is zero-padded; otherwise the call throws due to size mismatch.All requests are clamped to MaxDatagramPayloadSafe. This function performs exactly one kernel receive for the payload copy (no dummy read).
| [out] | buffer | [out] Destination buffer receiving exactly exactLen bytes on success. |
| [in] | exactLen | [in] Required logical length. Must be > 0. |
| [in] | opts | [in] Exact-read policy (requireExact, padIfSmaller) and base receive options. |
exactLen and the kernel truncated the payload.| SocketException | If the socket is not open, arguments are invalid, OS errors occur (message via SocketErrorMessage), or the size policy fails (e.g., mismatch with requireExact, or undersize without padIfSmaller). |
| SocketTimeoutException | If a receive timeout elapses before any datagram is available, or in non-blocking mode with no data. |
buffer is non-null; exactLen > 0. buffer holds exactly exactLen bytes (payload plus optional zero-padding).
|
inlinenodiscard |
Read one UDP datagram into a caller-provided byte container and optionally return the sender address/port.
| T | A contiguous byte container with data() and size(). Supports both dynamic (e.g., std::string, std::vector<char>) and fixed-size (e.g., std::array<char, N>) containers. |
Receives exactly one datagram and copies it into buffer. If T is dynamically resizable and a reliable size probe is available, the function grows buffer up front to the exact datagram size (clamped to MaxDatagramPayloadSafe) to avoid truncation and extra copies. Truncation behavior follows opts.errorOnTruncate:
When senderAddr and/or senderPort are non-null, the function resolves the numeric host and port of the datagram’s sender and writes them to the provided outputs. This works for both connected and unconnected sockets. If you only need the sender information without copying the payload into a DatagramPacket, this overload is convenient and zero-alloc for fixed buffers.
| [in,out] | buffer | Caller-provided destination container. For dynamic containers, it may be resized to fit the datagram. For fixed containers, its capacity limits the copy. |
| [out] | senderAddr | Optional. Receives the sender’s numeric IP string (e.g., "203.0.113.10"). |
| [out] | senderPort | Optional. Receives the sender’s port. |
| [in] | opts | Read options controlling preflight, truncation policy, and bookkeeping. |
buffer,buffer,| SocketException | If the socket is not open, OS-level receive errors occur (message via SocketErrorMessage), or truncation is disallowed by opts.errorOnTruncate and would occur. |
| SocketTimeoutException | If a receive timeout elapses before any datagram is available, or when the socket is non-blocking and no data is available (would-block). |
buffer contain the payload. If senderAddr and/or senderPort are provided, they contain the numeric sender address and port.
|
nodiscard |
Read one UDP datagram into a caller-provided span (zero allocation) with explicit truncation policy.
Performs exactly one receive to copy the next datagram into out, applying the policies in opts:
| [out] | out | Destination span receiving up to out.size() bytes. |
| [in] | opts | Read options controlling preflight, truncation policy, and “last remote” updates. |
out,out.| SocketException | If the socket is not open, OS-level receive errors occur (message via SocketErrorMessage), or truncation is disallowed by opts.errorOnTruncate. |
| SocketTimeoutException | If a receive timeout elapses before any datagram is available, or when the socket is non-blocking and no data is available (would-block). |
out contain the payload. When opts.updateLastRemote == true, the internal “last remote” reflects the sender.
|
nodiscard |
Read one UDP datagram into a caller-provided buffer with explicit truncation policy.
Performs exactly one receive to copy the next datagram into buffer, applying the policies in opts:
| [out] | buffer | Caller-provided destination buffer receiving up to len bytes. |
| [in] | len | Capacity of buffer in bytes. |
| [in] | opts | Read options controlling preflight, truncation policy, and “last remote” updates. |
buffer,buffer.| SocketException | If the socket is not open, arguments are invalid, OS-level receive errors occur (message via SocketErrorMessage), or truncation is disallowed by opts.errorOnTruncate. |
| SocketTimeoutException | If a receive timeout elapses before any datagram is available, or when the socket is non-blocking and no data is available (would-block). |
buffer is non-null, len > 0. buffer contain the payload. When opts.updateLastRemote == true, the internal “last remote” reflects the sender.
|
protected |
Low-level, single-recv primitive that copies one UDP datagram into a caller buffer.
Performs exactly one kernel receive. On POSIX, uses recvmsg and sets MSG_TRUNC (on Linux) to obtain precise truncation signaling; on Linux the return value with MSG_TRUNC reflects the full datagram size even when the buffer is smaller. When a size preflight is requested via mode, the next datagram size is queried (if supported) and the requested copy length is clamped accordingly. This function is policy-free: it never throws solely because truncation happened; instead it reports size and truncation through outDatagramSz and outTruncated so higher-level APIs can decide.
| [in,out] | buf | Destination buffer receiving up to len bytes. |
| [in] | len | Capacity of buf in bytes; the function never writes more than this. |
| [in] | mode | Receive mode. If not DatagramReceiveMode::NoPreflight, a size probe is attempted to refine the requested copy length. |
| [in] | recvFlags | Flags passed to the underlying receive. May be OR’ed with platform flags internally (e.g., MSG_TRUNC on Linux). |
| [out] | outSrc | Optional. Sender address as returned by the kernel. |
| [in,out] | outSrcLen | Optional. On input, capacity of outSrc. On output, actual size written. |
| [out] | outDatagramSz | Optional. Full datagram size when known (preflight or Linux+MSG_TRUNC); otherwise set to the copied byte count (best effort). |
| [out] | outTruncated | Optional. Set to true if the datagram did not fully fit in buf. |
buf (≤ len). May be 0 for a zero-length datagram.| SocketException | On invalid arguments, socket not open, or other OS-level errors (message via SocketErrorMessage). |
| SocketTimeoutException | If a configured receive timeout elapses before any datagram is received, or when the socket is non-blocking and no data is available (would-block). |
outSrc is non-null, outSrcLen points to a writable size. buf. When provided, outSrc/outSrcLen reflect the sender; outDatagramSz and outTruncated report size and truncation status.MaxDatagramPayloadSafe for safety. | std::size_t DatagramSocket::readIntoExact | ( | void * | buffer, |
| std::size_t | len ) const |
Strict exact-length UDP receive into a caller-provided buffer (single datagram).
Copies the next datagram into buffer and enforces that the datagram size matches len exactly. The method prefers an early, non-destructive failure: it attempts to probe the next datagram size first and throws before reading if the size is not exactly len. If a probe is not available on the platform, it performs one receive and throws afterward if the payload was truncated or shorter than len.
Behavior is equivalent to calling readExact(buffer, len, ReadExactOptions{ .requireExact = true, .padIfSmaller = false, .base.mode = DatagramReceiveMode::PreflightSize }). A single kernel receive is used for the payload copy; no allocation occurs.
| [out] | buffer | [out] Destination buffer that must have capacity for exactly len bytes. |
| [in] | len | [in] Required length in bytes; the datagram must be exactly this size. |
buffer. On success this equals len.| SocketException | If the socket is not open; arguments are invalid; OS-level receive errors occur (message via SocketErrorMessage); or the datagram size does not equal len. |
| SocketTimeoutException | If a configured receive timeout elapses before any datagram is available, or when the socket is non-blocking and no data is available (would-block). |
buffer is non-null. len > 0. len bytes have been written to buffer and the datagram queue advanced by one. On unconnected sockets, the internal “last remote” reflects the sender.
|
inlinenodiscard |
Read a length-prefixed UDP datagram and return the payload (prefix type T).
| T | Unsigned, trivially copyable integer type used for the length prefix (e.g., uint16_t, uint32_t, uint64_t). |
Expects the next datagram’s payload to begin with a T-sized length field followed by exactly that many payload bytes. The prefix is interpreted in the specified byte order and validated against the actual datagram size. The function:
sizeof(T) and that the prefix equals the remaining payload length.maxPayloadLen to guard against oversized frames.Works for connected and unconnected sockets; on unconnected sockets the internally tracked “last remote” endpoint is updated to the sender.
| [in] | maxPayloadLen | Maximum allowed payload length (not counting the prefix). Clamped to MaxDatagramPayloadSafe. Use to prevent pathological allocations. Defaults to MaxDatagramPayloadSafe. |
| [in] | prefixEndian | Byte order of the length prefix. Defaults to big-endian. |
std::string. Marked [[nodiscard]].| SocketException | If the socket is not open; the datagram is smaller than sizeof(T); the prefix/payload sizes mismatch; the payload exceeds maxPayloadLen; or on OS-level receive errors (message via SocketErrorMessage). |
| SocketTimeoutException | If a receive timeout elapses before any datagram is available, or when the socket is non-blocking and no data is available (would-block). |
readAtMost(...) instead.
|
nodiscard |
Scatter-gather receive: read one UDP datagram into multiple non-contiguous buffers.
Copies the next datagram across the spans in buffers using a single kernel receive:
| [in,out] | buffers | Scatter list of writable buffers; each entry must have a valid pointer when its size > 0. |
| [in] | opts | Read options controlling preflight, truncation policy, sender bookkeeping, and flags. |
| SocketException | If the socket is not open; buffer arguments are invalid; OS-level errors occur (message via SocketErrorMessage); or truncation is disallowed by opts.errorOnTruncate. |
| SocketTimeoutException | If a receive timeout elapses before any datagram is available, or when the socket is non-blocking and no data is available (would-block). |
|
nodiscard |
Scatter-gather receive that guarantees the entire next datagram fits the provided buffers.
Performs exactly one kernel receive to copy the full datagram across buffers in order. If the datagram would not fit in the aggregate capacity, the call fails before reading when a size probe is available; otherwise, it performs one receive and fails after the read if truncation occurred. This is a strict, no-truncation variant of readv(...).
On unconnected sockets, when opts.updateLastRemote == true, the internally tracked “last remote” endpoint is updated to the sender of this datagram.
| [in,out] | buffers | Scatter list of writable buffers. Each view must have a valid pointer when its size > 0. |
| [in] | opts | Read options. This method forces errorOnTruncate = true and prefers a size preflight (mode = PreflightSize when the caller left it as NoPreflight). |
buffers (equals the datagram size on success),| SocketException | If the socket is not open; buffer arguments are invalid; OS-level errors occur (message via SocketErrorMessage); or the datagram does not fit the provided capacity. |
| SocketTimeoutException | If a receive timeout elapses before any datagram is available, or when the socket is non-blocking and no data is available (would-block). |
buffers and removed from the queue.
|
inline |
Back-compat convenience returning only the number of bytes copied.
| [in,out] | buffers | See readvAll(std::span<BufferView>, const DatagramReadOptions&) const |
| [in] | opts | See readvAll(std::span<BufferView>, const DatagramReadOptions&) const |
|
nodiscard |
Scatter-gather, strict no-truncation receive with a per-call total timeout.
Waits up to totalTimeoutMillis milliseconds for the socket to become readable, then performs a single scatter-gather receive that must copy the entire next datagram into buffers. If the datagram would not fit in the aggregate capacity, the call fails (either before reading when a size probe is available, or after the read if not). This is a timed variant of readvAll(...).
The readiness wait uses poll/WSAPoll via hasPendingData(...), so this per-call timeout does not modify the socket’s global receive timeout. On unconnected sockets, when opts.updateLastRemote == true, the internally tracked “last remote” endpoint is updated to the sender of this datagram.
| [in,out] | buffers | Scatter list of writable buffers. Each view must have a valid pointer when its size > 0. |
| [in] | totalTimeoutMillis | Total timeout in milliseconds (>= 0). 0 performs a non-blocking readiness check. |
| [in] | opts | Read options. This method enforces strict no-truncation by setting errorOnTruncate = true and preferring a size preflight (mode = PreflightSize when left as NoPreflight). Other fields are honored. |
| SocketException | If the socket is not open; buffer arguments are invalid; OS-level errors occur (message via SocketErrorMessage); or the datagram does not fit the provided capacity. |
| SocketTimeoutException | If no datagram becomes ready within totalTimeoutMillis, or when the socket is non-blocking and no data is available. |
totalTimeoutMillis >= 0. buffers and removed from the queue. For unconnected sockets, when opts.updateLastRemote == true, the internal “last remote” reflects the sender.
|
inline |
Convenience wrapper returning only the number of bytes copied.
|
inline |
Convenience wrapper returning only the number of bytes read.
|
nodiscard |
Scatter-gather, best-effort read of the next datagram with a per-call timeout.
Waits up to timeoutMillis milliseconds for the socket to become readable, then performs a single-recv, at-most scatter-gather read into buffers:
buffers (clamped by MaxDatagramPayloadSafe).On unconnected sockets, when opts.updateLastRemote == true, the internally tracked “last remote” endpoint is updated to the sender of this datagram.
| [in,out] | buffers | Scatter list of writable buffers; each entry must have a valid pointer if its size > 0. |
| [in] | timeoutMillis | Timeout in milliseconds (>= 0). 0 means non-blocking readiness check. |
| [in] | opts | Read options; fields other than mode and errorOnTruncate are honored. This method forces mode = DatagramReceiveMode::NoPreflight and errorOnTruncate = false to ensure single-recv, best-effort behavior. |
| SocketException | If the socket is not open; buffer arguments are invalid; or an OS-level error occurs (message via SocketErrorMessage). |
| SocketTimeoutException | If no datagram becomes ready within timeoutMillis, or when the socket is non-blocking and no data is available (would-block). |
timeoutMillis >= 0. buffers.
|
staticprotected |
Resolve a host string to an IPv4 address (in_addr, network byte order).
Converts host into an IPv4 address suitable for socket APIs. Resolution strategy:
host is an IPv4 literal (e.g., "239.1.2.3"), parse it with inet_pton(AF_INET, ...) without any name-service lookup.The returned in_addr is in network byte order, ready for setsockopt, sendto, and multicast membership structures.
| [in] | host | Host string to resolve. Accepts IPv4 literals ("A.B.C.D") or names/hostnames resolvable by the system’s name services. Must not be empty. |
host is not empty.| SocketException |
|
|
staticprotected |
Resolve a host string to an IPv6 address (in6_addr).
Converts host into an IPv6 address suitable for socket APIs. Resolution strategy:
host is an IPv6 literal (e.g., "ff02::1"), parse it with inet_pton(AF_INET6, ...) and avoid any name-service lookup.The returned in6_addr is in the canonical struct form expected by socket calls, multicast membership records, and IPv6 setsockopt options.
| [in] | host | Host string to resolve. Accepts IPv6 literals (e.g., "ff02::1", "2001:db8::1") or names/hostnames resolvable by the system’s name services. Must not be empty. |
host is not empty.| SocketException |
|
|
inlineprotected |
Build and send a length-prefixed UDP datagram to the connected peer (no pre-wait).
| T | Unsigned integral type used for the length prefix (e.g., std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t). A compile-time check enforces that T is an unsigned integral. |
Constructs a single datagram with layout [ prefix(T, big-endian) | payload ] where the prefix encodes payload.size() in network byte order. The method: 1) verifies the socket is open and connected; 2) encodes the prefix via encodeLengthPrefixBE<T>(payload.size()); 3) computes total = sizeof(T) + payload.size() and enforces the connected peer’s protocol maxima via enforceSendCapConnected(total) (prevents guaranteed EMSGSIZE); 4) coalesces [prefix|payload] into one contiguous buffer and performs one send.
This function does not poll for writability. On non-blocking sockets, if the send buffer is temporarily full, the underlying send may fail (e.g., EWOULDBLOCK / WSAEWOULDBLOCK) and will be surfaced as a SocketException. For blocking behavior, prefer writeAll() or writeWithTimeout().
Atomicity: UDP is message-oriented; on success, the entire [prefix|payload] frame is sent in a single datagram. On exception, no bytes are considered transmitted.
Zero-length payloads are valid: a datagram containing only the prefix is sent.
| [in] | payload | Binary bytes to append after the length prefix (may be empty). |
| SocketException |
|
|
inlineprotected |
Build and send a length-prefixed UDP datagram to (host, port) on the unconnected path.
| T | Unsigned integral type for the length prefix (e.g., std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t). A compile-time check enforces that T is unsigned integral. |
Constructs a single frame [ prefix(T, big-endian) | payload ], where the prefix encodes payload.size() in network byte order, then transmits it to the specified destination using sendUnconnectedTo(). That helper resolves A/AAAA records, skips address families whose theoretical UDP maximum cannot carry the frame, attempts a single send to the first compatible candidate, and caches the last destination (without marking the socket connected).
Processing steps: 1) Verify socket is open. 2) Encode prefix via encodeLengthPrefixBE<T>(payload.size()) (validates that size fits in T). 3) Coalesce [prefix|payload] once and dispatch through sendUnconnectedTo(host, port, ...).
Zero-length payloads are valid: a datagram containing only the prefix is sent.
Atomicity: UDP is message-oriented; on success the entire [prefix|payload] frame is sent in one datagram. On exception, no bytes are considered transmitted.
| [in] | host | Destination hostname or numeric address (IPv4/IPv6). |
| [in] | port | Destination UDP port (> 0). |
| [in] | payload | Binary bytes to append after the length prefix (may be empty). |
| SocketException |
|
|
protected |
Resolve and send one unconnected UDP datagram to the first compatible destination.
Resolves host and port (AF_UNSPEC, UDP), iterates all A/AAAA candidates, and:
len (MaxUdpPayloadIPv4/MaxUdpPayloadIPv6).If no candidates can even be attempted (e.g., payload > IPv6 max or only A records for a payload that requires IPv6), throws a logical SocketException with a clear diagnostic. If at least one attempt is made and all fail, throws a SocketException with the last OS error (GetSocketError()/SocketErrorMessage()).
This helper is intended for all unconnected write paths (e.g., writeTo(...), write(const DatagramPacket&) when the packet specifies a destination).
| [in] | host | Destination hostname or numeric address (IPv4/IPv6). |
| [in] | port | Destination UDP port (> 0). |
| [in] | data | Pointer to payload (may be null iff len == 0). |
| [in] | len | Number of bytes to send in a single UDP datagram. |
| SocketException |
|
| void DatagramSocket::setInternalBufferSize | ( | std::size_t | newLen | ) |
Sets the size of the internal buffer used for string-based UDP receive operations.
This method controls the size of the internal buffer used internally by read<std::string>(). It does not affect the operating system's socket-level receive buffer (SO_RCVBUF), nor does it apply to fixed-size read<T>() calls.
| [in] | newLen | New size (in bytes) for the internal buffer |
| std::bad_alloc | If resizing the buffer fails due to memory allocation |
| void MulticastSocket::setLoopbackMode | ( | bool | enable | ) |
Enable or disable multicast loopback for this socket.
Controls whether multicast datagrams sent by this socket may be delivered back to the local host (i.e., whether the sender can observe its own multicast transmissions). This affects local delivery only — it does not change what remote receivers get.
This setting is per-socket and applies to multicast only. It does not affect unicast traffic.
| [in] | enable | Set true to allow local delivery of this socket’s multicast transmissions, or false to suppress local delivery. |
| SocketException | If the option cannot be applied. The exception carries the OS error code and a descriptive message produced by SocketErrorMessage(...). |
| void MulticastSocket::setMulticastInterface | ( | const std::string & | iface | ) |
Select the default outgoing interface for multicast transmissions.
Sets the per-socket egress interface that will be used for subsequent multicast sends. This is a convenience wrapper that accepts human-friendly identifiers and delegates to the per-family setters.
Accepted forms for iface
Behavior
iface is empty, the method resets the egress only for the socket’s actual family (IPv4 or IPv6) and clears the cached _currentInterface.iface parses as an IPv4 literal, the IPv4 egress is set and the cache is updated to the provided string.iface is interpreted as an IPv6 identifier and converted to an index using toIfIndexFromString(iface); the IPv6 egress is set and the cache is updated to the provided string.Notes
| [in] | iface | Interface selector as described above. Pass "" to reset to the per-family system default. |
| SocketException |
|
| void MulticastSocket::setTimeToLive | ( | int | ttl | ) |
Set the time-to-live (TTL) / hop limit for outgoing multicast packets.
Sets this socket’s default multicast scope for subsequent transmissions:
The value constrains how far outbound multicast packets may propagate:
This setting is per-socket and affects multicast only. Unicast scope is controlled independently via IP_TTL / IPV6_UNICAST_HOPS. Per-message control data (e.g., IP_MULTICAST_TTL or IPV6_HOPLIMIT with sendmsg) can override this default for individual packets.
| [in] | ttl | Hop limit (IPv6) or TTL (IPv4), in the range [0, 255]. |
| SocketException | If validation fails or the operating system rejects the option. The exception includes the OS error code and a descriptive message from SocketErrorMessage(...). |
|
inlinestaticprotected |
Throw a descriptive exception when a UDP datagram’s size differs from what was expected.
Emits a uniform, user-friendly error when the size of the next datagram does not match the caller’s expectation. This is typically used after either:
The exception message intentionally distinguishes whether the actual value came from a prior probe versus a receive operation, to aid debugging (reordering, truncation, or races between probe and read).
This function does not perform any I/O and does not modify socket state; it simply constructs and throws a SocketException with a clear message.
| [in] | expected | The number of bytes the caller expected to be present in the next datagram. |
| [in] | actual | The number of bytes observed (either probed or received). |
| [in] | isProbedKnown | Set to true if actual comes from a size probe; set to false if it reflects the size actually received from a recv/recvfrom call. |
| SocketException |
|
|
nodiscardprotected |
Retrieve the remote endpoint sockaddr for this socket, if available.
Determines the current remote peer (address + port) and writes it to the provided output buffers. The method prefers already-cached information:
This function is const and does not mutate any internal cache; it only reads cached values if present, or queries the OS once when connected.
| [out] | out | Destination for the remote endpoint (sockaddr_storage). |
| [out] | outLen | Receives the byte size of out (e.g., sizeof(sockaddr_in) or sizeof(sockaddr_in6)). |
| true | A remote endpoint was available and has been written to out/ |
| false | The socket is unconnected and no last-seen sender has been cached yet. |
| SocketException |
|
| void DatagramSocket::waitReady | ( | Direction | dir, |
| int | timeoutMillis ) const |
Block until the socket is ready for I/O or a timeout occurs.
Waits for the connected UDP socket to become ready for the requested operation(s) using a portable polling primitive (poll on POSIX, WSAPoll on Windows). This method does not change the socket’s blocking mode and is safe to call on both blocking and non-blocking sockets.
Timeout semantics
If an exceptional condition is reported by the OS (e.g., POLLERR, POLLNVAL, POLLHUP), this function retrieves SO_ERROR when available and throws a SocketException with that error code/message.
| [in] | dir | Readiness to wait for: Direction::Read, Direction::Write, or Direction::ReadWrite. |
| [in] | timeoutMillis | Timeout in milliseconds (see semantics above). |
| SocketTimeoutException | If the requested readiness is not achieved before the timeout. |
| SocketException | On polling failure or detected socket error (uses GetSocketError() and SocketErrorMessage()). |
| void DatagramSocket::write | ( | const DatagramPacket & | packet | ) |
Send one UDP datagram using a packet’s buffer and optional explicit destination.
Emits exactly one datagram whose payload is packet.buffer. Behavior depends on whether the packet specifies a destination:
Processing steps: 1) Verify the socket is open. 2) If packet.buffer.empty(), return immediately (zero-length datagrams are valid but skipped). 3) If the packet carries a destination, forward to sendUnconnectedTo(...). 4) Otherwise, require isConnected() == true, guard size with enforceSendCapConnected(...), and send.
Atomicity: UDP is message-oriented; on success, the entire packet.buffer is sent as one datagram. On exception, no bytes are considered transmitted.
| [in] | packet | The packet whose buffer supplies the payload and whose address/port (if present) select the destination for unconnected sends. |
| SocketException |
|
|
inline |
Send one UDP datagram whose payload is the raw object representation of value.
| T | Trivially copyable, standard-layout type whose in-memory object representation will be sent verbatim as the datagram payload. (See Implementation notes.) |
Emits exactly one datagram containing the bytes of value. This method performs an immediate send attempt (no pre-wait). Use writeAll() or writeWithTimeout() if you need the call to block until the socket is writable.
Processing steps:
⚠️ Serialization & portability
Atomicity: UDP is message-oriented; on success, there are no partial sends. Any failure is reported via exception and no bytes are considered transmitted.
| [in] | value | The value to send; its bytes (object representation) become the datagram payload. |
| SocketException |
|
| void DatagramSocket::write | ( | std::span< const std::byte > | data | ) | const |
Send one UDP datagram to the connected peer from a raw byte span (no pre-wait).
Emits exactly one datagram containing the bytes referenced by data. This method performs an immediate send attempt:
This function does not poll for writability. On non-blocking sockets, if the send buffer is full, the send may fail (e.g., EWOULDBLOCK/WSAEWOULDBLOCK) and a SocketException is thrown. If you need backpressure handling, use writeAll() (infinite wait) or writeWithTimeout() (bounded wait) instead.
Atomicity: UDP is message-oriented; on success the entire span is sent as one datagram. On exception, no bytes are considered transmitted.
| [in] | data | Contiguous read-only bytes to send as a single datagram. |
| SocketException |
|
| void DatagramSocket::write | ( | std::string_view | message | ) | const |
Send one UDP datagram to the currently connected peer (no pre-wait).
Emits exactly one datagram containing the bytes in message. This method performs an immediate send attempt:
This function does not poll or wait for writability. On non-blocking sockets, if the send buffer is temporarily full, the underlying send may fail (e.g., EWOULDBLOCK/WSAEWOULDBLOCK) and a SocketException is thrown. If you need the method to wait until the socket is writable, use writeAll() or one of the timeout variants instead.
Atomicity: UDP is message-oriented; on success, the entire payload is sent in one datagram (no partial sends). Failures are reported via exceptions—no bytes are considered transmitted on exception.
| [in] | message | Bytes to send as a single datagram. Accepts std::string, string literals, and other contiguous character sequences via implicit conversion to std::string_view. |
| SocketException |
|
| void DatagramSocket::writeAll | ( | std::string_view | message | ) | const |
Send one UDP datagram to the connected peer, waiting indefinitely for writability.
Emits exactly one datagram containing message. Unlike write(), this method pre-waits for the socket to become writable so it behaves consistently on both blocking and non-blocking sockets:
Atomicity: On success the entire payload is sent in one datagram. On exception, no bytes are considered transmitted.
| [in] | message | Bytes to send as a single datagram. |
| SocketException |
|
| void DatagramSocket::writeFrom | ( | const void * | data, |
| std::size_t | len ) const |
Send one UDP datagram to the connected peer from a raw memory buffer (no pre-wait).
Emits exactly one datagram containing the first len bytes starting at data. This method performs an immediate send attempt (it does not poll for writability):
len is zero, returns immediately (zero-length UDP datagrams are valid, but this implementation skips the syscall as a micro-optimization).This function does not pre-wait for writability. On non-blocking sockets, if the send buffer is temporarily full, the underlying send may fail (e.g., EWOULDBLOCK / WSAEWOULDBLOCK) and a SocketException is thrown. For blocking behavior, use writeAll() (infinite wait) or writeWithTimeout() (bounded wait).
Ownership/Lifetime: The memory referenced by data is not copied or retained beyond the duration of the call; it must remain valid and readable until the call returns.
Atomicity: UDP is message-oriented; on success, the entire buffer is sent as one datagram. On exception, no bytes are considered transmitted.
| [in] | data | Pointer to the first byte of the payload. May be nullptr iff len == 0. |
| [in] | len | Number of bytes to send as a single datagram. |
len bytes are handed to the kernel as one datagram. Socket state and options are unchanged.| SocketException |
|
|
inline |
Send a length-prefixed UDP datagram to the connected peer from a byte span (no pre-wait).
| T | Unsigned integral type for the length prefix. |
Builds [ prefix(T, big-endian) | payload ] and forwards to sendPrefixedConnected<T>(). Zero-length payloads yield a prefix-only datagram. This method performs an immediate send attempt (no pre-wait).
| [in] | payload | Binary payload to append after the length prefix. |
| SocketException | (same categories as the std::string_view overload). |
|
inline |
Send a length-prefixed UDP datagram to the connected peer from text bytes (no pre-wait).
| T | Unsigned integral type for the length prefix (e.g., std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t). A compile-time check in the helper enforces this. |
Wraps the payload as [ prefix(T, big-endian) | payload ] and forwards to sendPrefixedConnected<T>(). Zero-length payloads are valid: a prefix-only datagram is sent. This method performs an immediate send attempt (no pre-wait).
| [in] | payload | Text bytes to send after the length prefix. |
| SocketException |
|
|
inline |
Send a length-prefixed UDP datagram to (host, port) from a byte span (unconnected path).
| T | Unsigned integral type for the length prefix. |
Builds [ prefix(T, big-endian) | payload ] and forwards to sendPrefixedUnconnected<T>(). The helper resolves and selects a compatible destination (skipping families that can’t carry the frame) and sends once.
| [in] | host | Destination hostname or numeric address (IPv4/IPv6). |
| [in] | port | Destination UDP port (> 0). |
| [in] | payload | Binary payload to append after the length prefix. |
| SocketException | (same categories as the text overload). |
|
inline |
Send a length-prefixed UDP datagram to (host, port) from text bytes (unconnected path).
| T | Unsigned integral type for the length prefix. |
Builds [ prefix(T, big-endian) | payload ] and forwards to sendPrefixedUnconnected<T>(), which resolves A/AAAA, skips families that cannot carry the frame, and sends once to the first compatible destination. Zero-length payloads produce a prefix-only datagram.
| [in] | host | Destination hostname or numeric address (IPv4/IPv6). |
| [in] | port | Destination UDP port (> 0). |
| [in] | payload | Text bytes to append after the length prefix. |
| SocketException |
|
|
inline |
Send one unconnected UDP datagram to (host, port) containing the raw bytes of value.
| T | Trivially copyable, standard-layout type whose in-memory object representation will be sent verbatim as the datagram payload. Compile-time checks in the implementation enforce these constraints. |
Emits exactly one datagram whose payload is the raw bytes of value. This overload uses the unconnected send path and delegates to sendUnconnectedTo(), which:
host.Steps performed by this method: 1) Verify the socket is open. 2) If sizeof(T) == 0, return immediately. 3) Bit-cast value to a contiguous byte buffer. 4) Forward to sendUnconnectedTo(host, port, buf, sizeof(T)).
This function does not poll for writability. On non-blocking sockets, if a send is attempted and the send buffer is full, the underlying send may fail (EWOULDBLOCK / WSAEWOULDBLOCK) and will be surfaced as a SocketException. For blocking semantics on a connected socket, prefer writeAll() or writeWithTimeout().
Serialization and portability:
Atomicity:
| [in] | host | Destination hostname or numeric address (IPv4/IPv6). |
| [in] | port | Destination UDP port (> 0). |
| [in] | value | The value whose bytes form the datagram payload. |
| SocketException |
|
| void DatagramSocket::writeTo | ( | std::string_view | host, |
| Port | port, | ||
| std::span< const std::byte > | data ) |
Send one unconnected UDP datagram to (host, port) from a raw byte span (no pre-wait).
Emits exactly one datagram containing data to the specified destination. This overload uses the unconnected send path and delegates to sendUnconnectedTo(), which:
host.Steps performed by this method: 1) Verify the socket is open. 2) If data.empty(), return immediately (zero-length UDP datagrams are valid, but this implementation skips the syscall as a micro-optimization). 3) Forward to sendUnconnectedTo(host, port, data.data(), data.size()).
This function does not poll for writability. On non-blocking sockets, if an attempt is made and the send buffer is full, the underlying send may fail (EWOULDBLOCK / WSAEWOULDBLOCK) and will be surfaced as a SocketException. For blocking semantics on a connected socket, prefer writeAll() or writeWithTimeout().
Atomicity: UDP is message-oriented; on success, the entire span is sent as one datagram. On exception, no bytes are considered transmitted.
| [in] | host | Destination hostname or numeric address (IPv4/IPv6). |
| [in] | port | Destination UDP port (> 0). |
| [in] | data | Contiguous read-only bytes to send as a single datagram. |
| SocketException |
|
| void DatagramSocket::writeTo | ( | std::string_view | host, |
| Port | port, | ||
| std::string_view | message ) |
Send one unconnected UDP datagram to (host, port) from text bytes (no pre-wait).
Emits exactly one datagram containing message to the specified destination. This overload uses the unconnected send path and delegates the heavy lifting to sendUnconnectedTo(), which:
host.Steps performed by this method: 1) Verify the socket is open. 2) If message.empty(), return immediately (zero-length UDP datagrams are valid, but this implementation skips the syscall as a micro-optimization). 3) Forward to sendUnconnectedTo(host, port, message.data(), message.size()).
This function does not poll for writability. On non-blocking sockets, if an attempt is made and the send buffer is full, the underlying send may fail (EWOULDBLOCK / WSAEWOULDBLOCK) and will be surfaced as a SocketException. For blocking semantics on a connected socket, prefer writeAll() or writeWithTimeout().
Atomicity: UDP is message-oriented; on success, the entire payload is sent as one datagram. On exception, no bytes are considered transmitted.
| [in] | host | Destination hostname or numeric address (IPv4/IPv6). |
| [in] | port | Destination UDP port (> 0). |
| [in] | message | Bytes to send as a single datagram (accepts std::string, string literals, etc., via implicit conversion to std::string_view). |
| SocketException |
|
| void DatagramSocket::writev | ( | std::span< const std::string_view > | buffers | ) | const |
Send one UDP datagram to the connected peer by concatenating multiple fragments (no pre-wait).
Emits exactly one datagram whose payload is the concatenation of all strings in buffers. This method performs an immediate send attempt (it does not wait for writability):
This function does not pre-wait for writability. On non-blocking sockets, if the send buffer is full, the send may fail (e.g., EWOULDBLOCK / WSAEWOULDBLOCK) and a SocketException is thrown. Use writevAll() or writeWithTimeout() for blocking behavior.
Atomicity: UDP is message-oriented; on success the entire concatenated payload is sent as a single datagram. On exception, no bytes are considered transmitted.
| [in] | buffers | Sequence of string fragments that will be concatenated in-order into the datagram payload. Individual elements may be empty. |
| SocketException |
|
| void DatagramSocket::writevAll | ( | std::span< const std::string_view > | buffers | ) | const |
Send one UDP datagram to the connected peer by concatenating multiple fragments, waiting indefinitely.
Emits exactly one datagram whose payload is the concatenation of all strings in buffers. Unlike writev(), this method pre-waits for writability so it behaves consistently on both blocking and non-blocking sockets:
Atomicity: UDP is message-oriented; on success, the entire concatenated payload is sent as a single datagram. On exception, no bytes are considered transmitted.
| [in] | buffers | Sequence of string fragments concatenated in-order into the datagram payload. Individual elements may be empty. |
| SocketException |
|
| void DatagramSocket::writeWithTimeout | ( | std::string_view | data, |
| int | timeoutMillis ) const |
Send one UDP datagram to the connected peer, waiting up to timeoutMillis for writability.
Emits exactly one datagram containing data. This method bounds the wait for socket writability, then performs a single send:
Timeout semantics (delegated to waitReady()):
Atomicity: UDP is message-oriented; on success, the entire payload is sent as one datagram. On exception, no bytes are considered transmitted.
| [in] | data | Bytes to send as a single datagram (accepts std::string, string literals, etc., via implicit conversion to std::string_view). |
| [in] | timeoutMillis | See timeout semantics above. |
| SocketTimeoutException | If the socket does not become writable within timeoutMillis (when it is >= 0). |
| SocketException |
|
timeoutMillis to mimic that behavior if you must stick to a single API.
|
overridenoexcept |
Destructor for DatagramSocket. Ensures socket resources are released.
Automatically closes the underlying UDP socket and releases all associated system resources. This follows RAII principles, guaranteeing cleanup when the object goes out of scope.