Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
vpUDPClient.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5 *
6 * This software is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * See the file LICENSE.txt at the root directory of this source
11 * distribution for additional information about the GNU GPL.
12 *
13 * For using ViSP with software that can not be combined with the GNU
14 * GPL, please contact Inria about acquiring a ViSP Professional
15 * Edition License.
16 *
17 * See https://visp.inria.fr for more information.
18 *
19 * This software was developed at:
20 * Inria Rennes - Bretagne Atlantique
21 * Campus Universitaire de Beaulieu
22 * 35042 Rennes Cedex
23 * France
24 *
25 * If you have questions regarding the use of this file, please contact
26 * Inria at visp@inria.fr
27 *
28 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * Description:
32 * UDP Client
33 *
34*****************************************************************************/
35
36#include <cstring>
37#include <sstream>
38
39#include <visp3/core/vpConfig.h>
40
41// inet_ntop() not supported on win XP
42#ifdef VISP_HAVE_FUNC_INET_NTOP
43
44#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
45#include <arpa/inet.h>
46#include <errno.h>
47#include <netdb.h>
48#include <unistd.h>
49#define DWORD int
50#else
51#if defined(__MINGW32__)
52#ifndef _WIN32_WINNT
53#define _WIN32_WINNT _WIN32_WINNT_VISTA // 0x0600
54#endif
55#endif
56#include <Ws2tcpip.h>
57#endif
58
59#include <visp3/core/vpUDPClient.h>
60
67 : m_is_init(false), m_serverAddress(), m_serverLength(0), m_socketFileDescriptor()
68#if defined(_WIN32)
69 ,
70 m_wsa()
71#endif
72{
73}
74
81vpUDPClient::vpUDPClient(const std::string &hostname, int port)
82 : m_is_init(false), m_serverAddress(), m_serverLength(0), m_socketFileDescriptor()
83#if defined(_WIN32)
84 ,
85 m_wsa()
86#endif
87{
88 init(hostname, port);
89}
90
95
99void vpUDPClient::close()
100{
101 if (m_is_init) {
102#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
103 ::close(m_socketFileDescriptor);
104#else
105 closesocket(m_socketFileDescriptor);
106 WSACleanup();
107#endif
108 m_is_init = false;
109 }
110}
111
118void vpUDPClient::init(const std::string &hostname, int port)
119{
120 // Close connexion if already initialized
121 close();
122
123#if defined(_WIN32)
124 if (WSAStartup(MAKEWORD(2, 2), &m_wsa) != 0) {
125 std::stringstream ss;
126 ss << "Failed WSAStartup for the server, error code: " << WSAGetLastError();
127 throw vpException(vpException::fatalError, ss.str());
128 }
129#endif
130
131 /* socket: create the socket */
132 m_socketFileDescriptor = socket(AF_INET, SOCK_DGRAM, 0);
133#if defined(_WIN32)
134 if (m_socketFileDescriptor == INVALID_SOCKET)
135#else
136 if (m_socketFileDescriptor < 0)
137#endif
138 throw vpException(vpException::fatalError, "Error opening UDP socket for the client!");
139
140 /* build the server's Internet address */
141 memset(&m_serverAddress, 0, sizeof(m_serverAddress));
142 std::stringstream ss;
143 ss << port;
144 struct addrinfo hints;
145 struct addrinfo *result = NULL;
146 struct addrinfo *ptr = NULL;
147
148 memset(&hints, 0, sizeof(hints));
149 hints.ai_family = AF_INET;
150 hints.ai_socktype = SOCK_DGRAM;
151 hints.ai_protocol = IPPROTO_UDP;
152
153 DWORD dwRetval = getaddrinfo(hostname.c_str(), ss.str().c_str(), &hints, &result);
154 if (dwRetval != 0) {
155 ss.str("");
156 ss << "getaddrinfo failed with error: " << dwRetval;
157 throw vpException(vpException::fatalError, ss.str());
158 }
159
160 for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
161 if (ptr->ai_family == AF_INET && ptr->ai_socktype == SOCK_DGRAM) {
162 m_serverAddress = *(struct sockaddr_in *)ptr->ai_addr;
163 break;
164 }
165 }
166
167 freeaddrinfo(result);
168
169 m_serverLength = sizeof(m_serverAddress);
170 m_is_init = true;
171}
172
195int vpUDPClient::receive(std::string &msg, int timeoutMs)
196{
197 if (!m_is_init) {
198 throw(vpException(vpException::notInitialized, "UDP client is not initialized"));
199 }
200 fd_set s;
201 FD_ZERO(&s);
202 FD_SET(m_socketFileDescriptor, &s);
203 struct timeval timeout;
204 if (timeoutMs > 0) {
205 timeout.tv_sec = timeoutMs / 1000;
206 timeout.tv_usec = (timeoutMs % 1000) * 1000;
207 }
208 int retval = select((int)m_socketFileDescriptor + 1, &s, NULL, NULL, timeoutMs > 0 ? &timeout : NULL);
209
210 if (retval == -1) {
211 std::cerr << "Error select!" << std::endl;
212 return -1;
213 }
214
215 if (retval > 0) {
216 /* recvfrom: receive a UDP datagram from the server */
217 int length = static_cast<int>(recvfrom(m_socketFileDescriptor, m_buf, sizeof(m_buf), 0,
218 (struct sockaddr *)&m_serverAddress, (socklen_t *)&m_serverLength));
219 if (length <= 0) {
220 return length < 0 ? -1 : 0;
221 }
222
223 msg = std::string(m_buf, length);
224 return length;
225 }
226
227 // Timeout
228 return 0;
229}
230
241int vpUDPClient::receive(void *msg, size_t len, int timeoutMs)
242{
243 if (!m_is_init) {
244 throw(vpException(vpException::notInitialized, "UDP client is not initialized"));
245 }
246 fd_set s;
247 FD_ZERO(&s);
248 FD_SET(m_socketFileDescriptor, &s);
249 struct timeval timeout;
250 if (timeoutMs > 0) {
251 timeout.tv_sec = timeoutMs / 1000;
252 timeout.tv_usec = (timeoutMs % 1000) * 1000;
253 }
254 int retval = select((int)m_socketFileDescriptor + 1, &s, NULL, NULL, timeoutMs > 0 ? &timeout : NULL);
255
256 if (retval == -1) {
257 std::cerr << "Error select!" << std::endl;
258 return -1;
259 }
260
261 if (retval > 0) {
262 /* recvfrom: receive a UDP datagram from the server */
263 int length = static_cast<int>(recvfrom(m_socketFileDescriptor, (char *)msg, (int)len, 0,
264 (struct sockaddr *)&m_serverAddress, (socklen_t *)&m_serverLength));
265 if (length <= 0) {
266 return length < 0 ? -1 : 0;
267 }
268
269 return length;
270 }
271
272 // Timeout
273 return 0;
274}
275
301int vpUDPClient::send(const std::string &msg)
302{
303 if (!m_is_init) {
304 throw(vpException(vpException::notInitialized, "UDP client is not initialized"));
305 }
306 if (msg.size() > VP_MAX_UDP_PAYLOAD) {
307 std::cerr << "Message is too long!" << std::endl;
308 return 0;
309 }
310
311/* send the message to the server */
312#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
313 return static_cast<int>(
314 sendto(m_socketFileDescriptor, msg.c_str(), msg.size(), 0, (struct sockaddr *)&m_serverAddress, m_serverLength));
315#else
316 return sendto(m_socketFileDescriptor, msg.c_str(), (int)msg.size(), 0, (struct sockaddr *)&m_serverAddress,
317 m_serverLength);
318#endif
319}
320
330int vpUDPClient::send(const void *msg, size_t len)
331{
332 if (!m_is_init) {
333 throw(vpException(vpException::notInitialized, "UDP client is not initialized"));
334 }
335 if (len > VP_MAX_UDP_PAYLOAD) {
336 std::cerr << "Message is too long!" << std::endl;
337 return 0;
338 }
339
340/* send the message to the server */
341#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
342 return static_cast<int>(
343 sendto(m_socketFileDescriptor, msg, len, 0, (struct sockaddr *)&m_serverAddress, m_serverLength));
344#else
345 return sendto(m_socketFileDescriptor, (char *)msg, (int)len, 0, (struct sockaddr *)&m_serverAddress, m_serverLength);
346#endif
347}
348
349#elif !defined(VISP_BUILD_SHARED_LIBS)
350// Work around to avoid warning: libvisp_core.a(vpUDPClient.cpp.o) has no symbols
351void dummy_vpUDPClient(){};
352#endif
error that can be emitted by ViSP classes.
Definition vpException.h:59
@ notInitialized
Used to indicate that a parameter is not initialized.
Definition vpException.h:86
@ fatalError
Fatal error.
Definition vpException.h:84
int receive(std::string &msg, int timeoutMs=0)
virtual ~vpUDPClient()
void init(const std::string &hostname, int port)
int send(const std::string &msg)