jsocketpp 1.0
A cross-platform C++20 socket library.
Loading...
Searching...
No Matches
DatagramSocket.hpp
Go to the documentation of this file.
1
5
6#pragma once
7
8#include "DatagramPacket.hpp"
9#include "common.hpp"
10
11#include <string>
12
13namespace jsocketpp
14{
15
81{
82 public:
96 explicit DatagramSocket(Port port, std::size_t bufferSize = 2048);
97
105 DatagramSocket(std::string_view host, Port port, std::size_t bufferSize = 2048);
106
110 ~DatagramSocket() noexcept;
111
116
121
129 : _sockFd(other._sockFd), _addrInfoPtr(other._addrInfoPtr), _selectedAddrInfo(other._selectedAddrInfo),
130 _localAddr(other._localAddr), _localAddrLen(other._localAddrLen), _buffer(std::move(other._buffer)),
131 _port(other._port)
132 {
133 other._sockFd = INVALID_SOCKET;
134 other._addrInfoPtr = nullptr;
135 other._selectedAddrInfo = nullptr;
136 other._localAddrLen = 0;
137 other._port = 0;
138 }
139
146 {
147 if (this != &other)
148 {
149 close();
150 _sockFd = other._sockFd;
151 _localAddr = other._localAddr;
152 _localAddrLen = other._localAddrLen;
153 _addrInfoPtr = other._addrInfoPtr;
154 _selectedAddrInfo = other._selectedAddrInfo;
155 _buffer = std::move(other._buffer);
156 _port = other._port;
157
158 other._sockFd = INVALID_SOCKET;
159 other._addrInfoPtr = nullptr;
160 other._selectedAddrInfo = nullptr;
161 other._localAddrLen = 0;
162 other._port = 0;
163 }
164 return *this;
165 }
166
171 void bind() const;
172
200 void connect(int timeoutMillis = -1);
201
212 [[nodiscard]] size_t write(const DatagramPacket& packet) const;
213
221 [[nodiscard]] size_t write(std::string_view message) const;
222
231 [[nodiscard]] size_t write(std::string_view message, std::string_view host, Port port) const;
232
245 [[nodiscard]] size_t read(DatagramPacket& packet, bool resizeBuffer = true) const;
246
253 template <typename T> T read()
254 {
255 static_assert(std::is_trivially_copyable_v<T>,
256 "DatagramSocket::read<T>() only supports trivially copyable types");
257
258 if (!_isConnected)
259 throw SocketException(0, "DatagramSocket is not connected.");
260
261 T value;
262 const int n = ::recv(_sockFd, reinterpret_cast<char*>(&value), sizeof(T), 0);
263
264 if (n == SOCKET_ERROR)
266 if (n == 0)
267 throw SocketException(0, "Connection closed by remote host.");
268 if (n != sizeof(T))
269 throw SocketException(0, "Partial read: did not receive a complete T object.");
270 return value;
271 }
272
281 template <typename T> T recvFrom(std::string* senderAddr, Port* senderPort)
282 {
283 static_assert(std::is_trivially_copyable_v<T>, "recvFrom<T>() only supports trivially copyable types");
284
285 sockaddr_storage srcAddr{};
286 socklen_t srcLen = sizeof(srcAddr);
287 T value;
288 const auto n = ::recvfrom(_sockFd, reinterpret_cast<char*>(&value), sizeof(T), 0,
289 reinterpret_cast<sockaddr*>(&srcAddr), &srcLen);
290 if (n == SOCKET_ERROR)
292 if (n == 0)
293 throw SocketException(0, "Connection closed by remote host.");
294
295 // Get sender's IP:port
296 char hostBuf[NI_MAXHOST], portBuf[NI_MAXSERV];
297 if (getnameinfo(reinterpret_cast<sockaddr*>(&srcAddr), srcLen, hostBuf, sizeof(hostBuf), portBuf,
298 sizeof(portBuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0)
299 {
300 if (senderAddr)
301 *senderAddr = hostBuf;
302 if (senderPort)
303 *senderPort = static_cast<Port>(std::stoul(portBuf));
304 }
305 else
306 {
307 if (senderAddr)
308 senderAddr->clear();
309 if (senderPort)
310 *senderPort = 0;
311 }
312
313 return value;
314 }
315
319 void close();
320
326 void setNonBlocking(bool nonBlocking) const;
327
340 void setTimeout(int millis) const;
341
349 void setOption(int level, int optName, int value) const;
350
358 [[nodiscard]] int getOption(int level, int optName) const;
359
364 std::string getLocalSocketAddress() const;
365
370 [[nodiscard]] bool isValid() const { return _sockFd != INVALID_SOCKET; }
371
381 [[nodiscard]] bool isConnected() const { return this->_isConnected; }
382
388 void enableBroadcast(bool enable) const;
389
390 protected:
401 void cleanupAndThrow(int errorCode);
402
403 // Also required for MulticastSocket, hence protected.
405 addrinfo* _addrInfoPtr = nullptr;
406 addrinfo* _selectedAddrInfo = nullptr;
407
408 private:
409 sockaddr_storage _localAddr{};
410 mutable socklen_t _localAddrLen = 0;
411 std::vector<char> _buffer;
413 bool _isConnected = false;
414};
415
421template <> inline std::string DatagramSocket::read<std::string>()
422{
423 if (!_isConnected)
424 throw SocketException(0, "DatagramSocket is not connected.");
425
426 _buffer.resize(_buffer.size()); // Ensure buffer is sized
427 const auto n = ::recv(_sockFd, _buffer.data(),
428#ifdef _WIN32
429 static_cast<int>(_buffer.size()),
430#else
431 _buffer.size(),
432#endif
433 0);
434 if (n == SOCKET_ERROR)
436 if (n == 0)
437 throw SocketException(0, "Connection closed by remote host.");
438 return {_buffer.data(), static_cast<size_t>(n)};
439}
440
448template <> inline std::string DatagramSocket::recvFrom<std::string>(std::string* senderAddr, Port* senderPort)
449{
450 sockaddr_storage srcAddr{};
451 socklen_t srcLen = sizeof(srcAddr);
452 const auto n = ::recvfrom(_sockFd, _buffer.data(),
453#ifdef _WIN32
454 static_cast<int>(_buffer.size()),
455#else
456 _buffer.size(),
457#endif
458 0, reinterpret_cast<sockaddr*>(&srcAddr), &srcLen);
459 if (n == SOCKET_ERROR)
461 if (n == 0)
462 throw SocketException(0, "Connection closed by remote host.");
463
464 // Get sender's IP:port
465 char hostBuf[NI_MAXHOST], portBuf[NI_MAXSERV];
466 if (getnameinfo(reinterpret_cast<sockaddr*>(&srcAddr), srcLen, hostBuf, sizeof(hostBuf), portBuf, sizeof(portBuf),
467 NI_NUMERICHOST | NI_NUMERICSERV) == 0)
468 {
469 if (senderAddr)
470 *senderAddr = hostBuf;
471 if (senderPort)
472 *senderPort = static_cast<Port>(std::stoul(portBuf));
473 }
474 else
475 {
476 if (senderAddr)
477 senderAddr->clear();
478 if (senderPort)
479 *senderPort = 0;
480 }
481 return {_buffer.data(), static_cast<size_t>(n)};
482}
483
484} // namespace jsocketpp
UDP datagram packet class for jsocketpp.
Represents a UDP datagram packet, encapsulating both payload and addressing information.
Definition DatagramPacket.hpp:48
void cleanupAndThrow(int errorCode)
Cleans up datagram socket resources and throws a SocketException.
Definition DatagramSocket.cpp:80
T recvFrom(std::string *senderAddr, Port *senderPort)
Receive a datagram into a trivially copyable type.
Definition DatagramSocket.hpp:281
void setOption(int level, int optName, int value) const
Set a socket option (integer value).
Definition DatagramSocket.cpp:446
DatagramSocket & operator=(DatagramSocket &&other) noexcept
Move assignment operator.
Definition DatagramSocket.hpp:145
~DatagramSocket() noexcept
Destructor. Closes the socket and frees resources.
Definition DatagramSocket.cpp:89
DatagramSocket(const DatagramSocket &)=delete
Copy constructor (deleted).
void connect(int timeoutMillis=-1)
Connects the datagram socket to the remote host and port with optional timeout handling.
Definition DatagramSocket.cpp:123
socklen_t _localAddrLen
Length of local address.
Definition DatagramSocket.hpp:410
void setTimeout(int millis) const
Sets the socket's receive timeout.
Definition DatagramSocket.cpp:425
size_t read(DatagramPacket &packet, bool resizeBuffer=true) const
Receives a UDP datagram and fills the provided DatagramPacket.
Definition DatagramSocket.cpp:343
T read()
Read a trivially copyable type from the socket (connected UDP).
Definition DatagramSocket.hpp:253
int getOption(int level, int optName) const
Get a socket option (integer value).
Definition DatagramSocket.cpp:458
void bind() const
Bind the datagram socket to the configured port set in the constructor.
Definition DatagramSocket.cpp:101
std::string getLocalSocketAddress() const
Get the local socket's address as a string (ip:port).
Definition DatagramSocket.cpp:477
sockaddr_storage _localAddr
Local address structure.
Definition DatagramSocket.hpp:409
bool isConnected() const
Check if the datagram socket is connected to a remote host.
Definition DatagramSocket.hpp:381
DatagramSocket(Port port, std::size_t bufferSize=2048)
Constructs a UDP socket optionally bound to a local port.
Definition DatagramSocket.cpp:6
void close()
Close the datagram socket.
Definition DatagramSocket.cpp:390
DatagramSocket(DatagramSocket &&other) noexcept
Move constructor.
Definition DatagramSocket.hpp:128
void enableBroadcast(bool enable) const
Enable or disable the ability to send broadcast packets.
Definition DatagramSocket.cpp:508
DatagramSocket & operator=(const DatagramSocket &)=delete
Copy assignment operator (deleted).
void setNonBlocking(bool nonBlocking) const
Set the socket to non-blocking or blocking mode.
Definition DatagramSocket.cpp:406
Port _port
Port number the socket is bound to (if applicable).
Definition DatagramSocket.hpp:412
addrinfo * _selectedAddrInfo
Selected address info for connection.
Definition DatagramSocket.hpp:406
bool _isConnected
True if the socket is connected to a remote host.
Definition DatagramSocket.hpp:413
bool isValid() const
Check if the datagram socket is valid (open).
Definition DatagramSocket.hpp:370
SOCKET _sockFd
Underlying socket file descriptor.
Definition DatagramSocket.hpp:404
std::vector< char > _buffer
Internal buffer for read operations.
Definition DatagramSocket.hpp:411
addrinfo * _addrInfoPtr
Address info pointer for bind/connect.
Definition DatagramSocket.hpp:405
size_t write(const DatagramPacket &packet) const
Write data to a remote host using a DatagramPacket.
Definition DatagramSocket.cpp:232
Represents socket-related errors in the jsocketpp library.
Definition SocketException.hpp:58
Common platform and utility includes for jsocketpp.
std::uint16_t Port
Type alias representing a TCP or UDP port number (1–65535).
Definition common.hpp:315
A C++ socket library providing Java-style networking interfaces.
Definition BufferView.hpp:13
std::string SocketErrorMessage(int error, bool gaiStrerror=false)
Returns a human-readable error message for a socket error code.
Definition common.cpp:5
constexpr SOCKET INVALID_SOCKET
Definition common.hpp:220
int GetSocketError()
Definition common.hpp:202
int SOCKET
Definition common.hpp:219
constexpr SOCKET SOCKET_ERROR
Definition common.hpp:221