UDP sockets for Windows
Stefan Schuermans

Stefan Schuermans commited on 2017-10-28 20:24:17
Showing 4 changed files, with 444 additions and 0 deletions.

... ...
@@ -0,0 +1,148 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#include <winsock2.h>
7
+#include <string>
8
+
9
+#include "Io.h"
10
+#include "Udp4Addr.h"
11
+#include "Udp4Sock.h"
12
+
13
+namespace Blinker {
14
+
15
+/// constructor
16
+Udp4Sock::Udp4Sock()
17
+{
18
+  // create socket
19
+  m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
20
+  if (m_socket == INVALID_SOCKET)
21
+    return;
22
+
23
+  // switch to nonblocking mode
24
+  u_long nonblock = 1;
25
+  if (ioctlsocket(m_socket, FIONBIO, &nonblock) != 0) {
26
+    closesocket(m_socket);
27
+    m_socket = INVALID_SOCKET;
28
+    return;
29
+  }
30
+
31
+  // enable address re-use
32
+  BOOL opt = TRUE;
33
+  if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR,
34
+                 (char *)&opt, sizeof(opt)) != 0) {
35
+    closesocket(m_socket);
36
+    m_socket = INVALID_SOCKET;
37
+    return;
38
+  }
39
+}
40
+
41
+/// destructor
42
+Udp4Sock::~Udp4Sock()
43
+{
44
+  // exit if not initialized
45
+  if (m_socket == INVALID_SOCKET)
46
+    return;
47
+
48
+  // shutdown and close socket
49
+  shutdown(m_socket, SD_BOTH);
50
+  closesocket(m_socket);
51
+  m_socket = INVALID_SOCKET;
52
+}
53
+
54
+/**
55
+ * @brief get address the socket is bound to
56
+ * @param[out] addr local addess the socket is bound to
57
+ * @return if local address could be obtained
58
+ */
59
+bool Udp4Sock::getAddr(Udp4Addr &addr)
60
+{
61
+  struct sockaddr * sockaddr;
62
+  int socklen;
63
+
64
+  // exit with error if not initialized
65
+  if (m_socket == INVALID_SOCKET)
66
+    return false;
67
+
68
+  // get local name of socket
69
+  sockaddr = (struct sockaddr *)&addr.m_addr;
70
+  socklen = sizeof(addr.m_addr);
71
+  if (getsockname(m_socket, sockaddr, &socklen) != 0)
72
+    return false;
73
+  return socklen <= (int)sizeof(addr.m_addr); // check if not truncated
74
+}
75
+
76
+/**
77
+ * @brief bind socket
78
+ * @param[in] addr local address to bind to
79
+ * @return if binding succeeded
80
+ */
81
+bool Udp4Sock::bind(const Udp4Addr &addr)
82
+
83
+{
84
+  const struct sockaddr * sockaddr;
85
+  int socklen;
86
+
87
+  // exit with error if not initialized
88
+  if (m_socket == INVALID_SOCKET)
89
+    return false;
90
+
91
+  // bind
92
+  sockaddr = (const struct sockaddr *)&addr.m_addr;
93
+  socklen = sizeof(addr.m_addr);
94
+  return ::bind(m_socket, sockaddr, socklen) == 0;
95
+}
96
+
97
+/**
98
+ * @brief send to socket
99
+ * @param[in] data data to send in message
100
+ * @param[in] addr address the message should be sent to
101
+ * @return if the message could be sent
102
+ */
103
+bool Udp4Sock::send(const std::string &data, const Udp4Addr &addr)
104
+{
105
+  const struct sockaddr * sockaddr;
106
+  int socklen;
107
+  ssize_t len;
108
+
109
+  // exit with error if not initialized
110
+  if (m_socket == INVALID_SOCKET)
111
+    return false;
112
+
113
+  // send message
114
+  sockaddr = (const struct sockaddr *)&addr.m_addr;
115
+  socklen = sizeof(addr.m_addr);
116
+  len = sendto(m_socket, data.c_str(), data.size(), 0, sockaddr, socklen);
117
+  return len == (ssize_t)data.size();
118
+}
119
+
120
+/**
121
+ * @brief receive from socket
122
+ * @param[out] data data in received message
123
+ * @param[out] addr address the message has been received from
124
+ * @return if a message has been received
125
+ */
126
+bool Udp4Sock::recv(std::string &data, Udp4Addr &addr)
127
+{
128
+  char buf[65536];
129
+  struct sockaddr * sockaddr;
130
+  int socklen;
131
+  ssize_t len;
132
+
133
+  // exit with error if not initialized
134
+  if (m_socket == INVALID_SOCKET)
135
+    return false;
136
+
137
+  // receive message
138
+  sockaddr = (struct sockaddr *)&addr.m_addr;
139
+  socklen = sizeof(addr.m_addr);
140
+  len = recvfrom(m_socket, buf, sizeof(buf), 0, sockaddr, &socklen);
141
+  if (len < 0 || socklen > (int)sizeof(addr.m_addr)) // error or truncated
142
+    return false;
143
+  data.assign(buf, len);
144
+  return true;
145
+}
146
+
147
+} // namespace Blinker
148
+
... ...
@@ -0,0 +1,74 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#ifndef UDP4SOCK_H
7
+#define UDP4SOCK_H
8
+
9
+#include <winsock2.h>
10
+#include <string>
11
+
12
+#include "Io.h"
13
+#include "Udp4Addr.h"
14
+
15
+namespace Blinker {
16
+
17
+/**
18
+ * @brief UDP v4 socket
19
+ *
20
+ * UDP v4 socket in non-blocking mode with address re-usage enabled
21
+ */
22
+class Udp4Sock: public Io
23
+{
24
+public:
25
+  /// constructor
26
+  Udp4Sock();
27
+
28
+  /// destructor
29
+  ~Udp4Sock();
30
+
31
+private:
32
+  /// copy constructor disabled
33
+  Udp4Sock(const Udp4Sock &that);
34
+
35
+  /// assignment operator disabled
36
+  const Udp4Sock & operator=(const Udp4Sock &that);
37
+
38
+public:
39
+  /**
40
+   * @brief get address the socket is bound to
41
+   * @param[out] addr local addess the socket is bound to
42
+   * @return if local address could be obtained
43
+   */
44
+  bool getAddr(Udp4Addr &addr);
45
+
46
+  /**
47
+   * @brief bind socket
48
+   * @param[in] addr local address to bind to
49
+   * @return if binding succeeded
50
+   */
51
+  bool bind(const Udp4Addr &addr);
52
+
53
+  /**
54
+   * @brief send to socket
55
+   * @param[in] data data to send in message
56
+   * @param[in] addr address the message should be sent to
57
+   * @return if the message could be sent
58
+   */
59
+  bool send(const std::string &data, const Udp4Addr &addr);
60
+
61
+  /**
62
+   * @brief receive from socket
63
+   * @param[out] data data in received message
64
+   * @param[out] addr address the message has been received from
65
+   * @return if a message has been received
66
+   */
67
+  bool recv(std::string &data, Udp4Addr &addr);
68
+
69
+}; // class UdpSock
70
+
71
+} // namespace Blinker
72
+
73
+#endif // #ifndef UDP4SOCK_H
74
+
... ...
@@ -0,0 +1,148 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#include <winsock2.h>
7
+#include <string>
8
+
9
+#include "Io.h"
10
+#include "Udp6Addr.h"
11
+#include "Udp6Sock.h"
12
+
13
+namespace Blinker {
14
+
15
+/// constructor
16
+Udp6Sock::Udp6Sock()
17
+{
18
+  // create socket
19
+  m_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
20
+  if (m_socket == INVALID_SOCKET)
21
+    return;
22
+
23
+  // switch to nonblocking mode
24
+  u_long nonblock = 1;
25
+  if (ioctlsocket(m_socket, FIONBIO, &nonblock) != 0) {
26
+    closesocket(m_socket);
27
+    m_socket = INVALID_SOCKET;
28
+    return;
29
+  }
30
+
31
+  // enable address re-use
32
+  BOOL opt = TRUE;
33
+  if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR,
34
+                 (char *)&opt, sizeof(opt)) != 0) {
35
+    closesocket(m_socket);
36
+    m_socket = INVALID_SOCKET;
37
+    return;
38
+  }
39
+}
40
+
41
+/// destructor
42
+Udp6Sock::~Udp6Sock()
43
+{
44
+  // exit if not initialized
45
+  if (m_socket == INVALID_SOCKET)
46
+    return;
47
+
48
+  // shutdown and close socket
49
+  shutdown(m_socket, SD_BOTH);
50
+  closesocket(m_socket);
51
+  m_socket = INVALID_SOCKET;
52
+}
53
+
54
+/**
55
+ * @brief get address the socket is bound to
56
+ * @param[out] addr local addess the socket is bound to
57
+ * @return if local address could be obtained
58
+ */
59
+bool Udp6Sock::getAddr(Udp6Addr &addr)
60
+{
61
+  struct sockaddr * sockaddr;
62
+  int socklen;
63
+
64
+  // exit with error if not initialized
65
+  if (m_socket == INVALID_SOCKET)
66
+    return false;
67
+
68
+  // get local name of socket
69
+  sockaddr = (struct sockaddr *)&addr.m_addr;
70
+  socklen = sizeof(addr.m_addr);
71
+  if (getsockname(m_socket, sockaddr, &socklen) != 0)
72
+    return false;
73
+  return socklen <= (int)sizeof(addr.m_addr); // check if not truncated
74
+}
75
+
76
+/**
77
+ * @brief bind socket
78
+ * @param[in] addr local address to bind to
79
+ * @return if binding succeeded
80
+ */
81
+bool Udp6Sock::bind(const Udp6Addr &addr)
82
+
83
+{
84
+  const struct sockaddr * sockaddr;
85
+  int socklen;
86
+
87
+  // exit with error if not initialized
88
+  if (m_socket == INVALID_SOCKET)
89
+    return false;
90
+
91
+  // bind
92
+  sockaddr = (const struct sockaddr *)&addr.m_addr;
93
+  socklen = sizeof(addr.m_addr);
94
+  return ::bind(m_socket, sockaddr, socklen) == 0;
95
+}
96
+
97
+/**
98
+ * @brief send to socket
99
+ * @param[in] data data to send in message
100
+ * @param[in] addr address the message should be sent to
101
+ * @return if the message could be sent
102
+ */
103
+bool Udp6Sock::send(const std::string &data, const Udp6Addr &addr)
104
+{
105
+  const struct sockaddr * sockaddr;
106
+  int socklen;
107
+  ssize_t len;
108
+
109
+  // exit with error if not initialized
110
+  if (m_socket == INVALID_SOCKET)
111
+    return false;
112
+
113
+  // send message
114
+  sockaddr = (const struct sockaddr *)&addr.m_addr;
115
+  socklen = sizeof(addr.m_addr);
116
+  len = sendto(m_socket, data.c_str(), data.size(), 0, sockaddr, socklen);
117
+  return len == (ssize_t)data.size();
118
+}
119
+
120
+/**
121
+ * @brief receive from socket
122
+ * @param[out] data data in received message
123
+ * @param[out] addr address the message has been received from
124
+ * @return if a message has been received
125
+ */
126
+bool Udp6Sock::recv(std::string &data, Udp6Addr &addr)
127
+{
128
+  char buf[65536];
129
+  struct sockaddr * sockaddr;
130
+  int socklen;
131
+  ssize_t len;
132
+
133
+  // exit with error if not initialized
134
+  if (m_socket == INVALID_SOCKET)
135
+    return false;
136
+
137
+  // receive message
138
+  sockaddr = (struct sockaddr *)&addr.m_addr;
139
+  socklen = sizeof(addr.m_addr);
140
+  len = recvfrom(m_socket, buf, sizeof(buf), 0, sockaddr, &socklen);
141
+  if (len < 0 || socklen > (int)sizeof(addr.m_addr)) // error or truncated
142
+    return false;
143
+  data.assign(buf, len);
144
+  return true;
145
+}
146
+
147
+} // namespace Blinker
148
+
... ...
@@ -0,0 +1,74 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#ifndef UDP6SOCK_H
7
+#define UDP6SOCK_H
8
+
9
+#include <winsock2.h>
10
+#include <string>
11
+
12
+#include "Io.h"
13
+#include "Udp6Addr.h"
14
+
15
+namespace Blinker {
16
+
17
+/**
18
+ * @brief UDP v6 socket
19
+ *
20
+ * UDP v6 socket in non-blocking mode with address re-usage enabled
21
+ */
22
+class Udp6Sock: public Io
23
+{
24
+public:
25
+  /// constructor
26
+  Udp6Sock();
27
+
28
+  /// destructor
29
+  ~Udp6Sock();
30
+
31
+private:
32
+  /// copy constructor disabled
33
+  Udp6Sock(const Udp6Sock &that);
34
+
35
+  /// assignment operator disabled
36
+  const Udp6Sock & operator=(const Udp6Sock &that);
37
+
38
+public:
39
+  /**
40
+   * @brief get address the socket is bound to
41
+   * @param[out] addr local addess the socket is bound to
42
+   * @return if local address could be obtained
43
+   */
44
+  bool getAddr(Udp6Addr &addr);
45
+
46
+  /**
47
+   * @brief bind socket
48
+   * @param[in] addr local address to bind to
49
+   * @return if binding succeeded
50
+   */
51
+  bool bind(const Udp6Addr &addr);
52
+
53
+  /**
54
+   * @brief send to socket
55
+   * @param[in] data data to send in message
56
+   * @param[in] addr address the message should be sent to
57
+   * @return if the message could be sent
58
+   */
59
+  bool send(const std::string &data, const Udp6Addr &addr);
60
+
61
+  /**
62
+   * @brief receive from socket
63
+   * @param[out] data data in received message
64
+   * @param[out] addr address the message has been received from
65
+   * @return if a message has been received
66
+   */
67
+  bool recv(std::string &data, Udp6Addr &addr);
68
+
69
+}; // class UdpSock
70
+
71
+} // namespace Blinker
72
+
73
+#endif // #ifndef UDP6SOCK_H
74
+
0 75