Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpServer.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * TCP Server
32 */
33
34#include <visp3/core/vpConfig.h>
35
36// Specific case for UWP to introduce a workaround
37// error C4996: 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
38#if defined(WINRT) || defined(_WIN32)
39#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
40#define _WINSOCK_DEPRECATED_NO_WARNINGS
41#endif
42#endif
43
44// inet_ntop() not supported on win XP
45#ifdef VISP_HAVE_FUNC_INET_NTOP
46
47#include <sstream>
48
49#include <visp3/core/vpServer.h>
50#include <visp3/core/vpDebug.h>
51
52#if defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
53#include <TargetConditionals.h> // To detect OSX or IOS using TARGET_OS_IPHONE or TARGET_OS_IOS macro
54#endif
55
60vpServer::vpServer() : adress(), port(0), started(false), max_clients(10)
61{
62 int protocol = 0;
63 emitter.socketFileDescriptorEmitter = socket(AF_INET, SOCK_STREAM, protocol);
64#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
65 if (emitter.socketFileDescriptorEmitter < 0)
66#else
67 if (emitter.socketFileDescriptorEmitter == INVALID_SOCKET)
68#endif
69 {
70 vpERROR_TRACE("vpServer::vpServer(), cannot open socket.");
71 }
72 emitter.emitterAddress.sin_family = AF_INET;
73 emitter.emitterAddress.sin_addr.s_addr = INADDR_ANY;
74 emitter.emitterAddress.sin_port = 0;
75
76 adress = inet_ntoa(emitter.emitterAddress.sin_addr);
77 port = emitter.emitterAddress.sin_port;
78}
79
84vpServer::vpServer(const vpServer &server) : vpNetwork(server)
85{
86 *this = server;
87}
88
94{
95 adress = server.adress;
96 port = server.port;
97 started = server.started;
98 max_clients = server.max_clients;
99 return *this;
100}
101
107vpServer::vpServer(const int &port_serv) : adress(), port(0), started(false), max_clients(10)
108{
109 int protocol = 0;
110 emitter.socketFileDescriptorEmitter = socket(AF_INET, SOCK_STREAM, protocol);
111#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
112 if (emitter.socketFileDescriptorEmitter < 0)
113#else
114 if (emitter.socketFileDescriptorEmitter == INVALID_SOCKET)
115#endif
116 {
117 vpERROR_TRACE("vpServer::vpServer(const int &port_serv), cannot open socket.");
118 }
119 emitter.emitterAddress.sin_family = AF_INET;
120 emitter.emitterAddress.sin_addr.s_addr = INADDR_ANY; // inet_addr("127.0.0.1");
121 emitter.emitterAddress.sin_port = htons(static_cast<unsigned short>(port_serv));
122
123 adress = inet_ntoa(emitter.emitterAddress.sin_addr);
124 port = port_serv;
125}
126
133vpServer::vpServer(const std::string &adress_serv, const int &port_serv)
134 : adress(), port(0), started(false), max_clients(10)
135{
136 int protocol = 0;
137 emitter.socketFileDescriptorEmitter = socket(AF_INET, SOCK_STREAM, protocol);
138#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
139 if (emitter.socketFileDescriptorEmitter < 0)
140#else
141 if (emitter.socketFileDescriptorEmitter == INVALID_SOCKET)
142#endif
143 {
144 vpERROR_TRACE("vpServer::vpServer(const std::string &adress_serv,const "
145 "int &port_serv), cannot open socket.");
146 }
147 emitter.emitterAddress.sin_family = AF_INET;
148 emitter.emitterAddress.sin_addr.s_addr = inet_addr(adress_serv.c_str());
149 emitter.emitterAddress.sin_port = htons(static_cast<unsigned short>(port_serv));
150
151 adress = adress_serv;
152 port = port_serv;
153}
154
159{
160#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
161 close(emitter.socketFileDescriptorEmitter);
162#else // Win32
163 closesocket(static_cast<unsigned int>(emitter.socketFileDescriptorEmitter));
164#endif
165
166 for (unsigned int i = 0; i < receptor_list.size(); i++)
167#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
168 close(receptor_list[i].socketFileDescriptorReceptor);
169#else // Win32
170 closesocket(static_cast<unsigned int>(receptor_list[i].socketFileDescriptorReceptor));
171#endif
172}
173
180{
181 int serverStructLength = sizeof(emitter.emitterAddress);
182#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
183 int bindResult = bind(emitter.socketFileDescriptorEmitter, (struct sockaddr *)&emitter.emitterAddress,
184 static_cast<unsigned int>(serverStructLength));
185#else // Win32
186 int bindResult = bind(static_cast<unsigned int>(emitter.socketFileDescriptorEmitter), (struct sockaddr *)&emitter.emitterAddress,
187 serverStructLength);
188#endif
189
190 if (bindResult < 0) {
191 std::cout << "Error id : " << bindResult << std::endl;
192 std::stringstream errorMessage;
193 errorMessage << "vpServer::vpServer(), cannot bind to port";
194 errorMessage << " ";
195 errorMessage << port;
196 errorMessage << " The port may be already used.";
197
198 vpERROR_TRACE(errorMessage.str().c_str());
199 return false;
200 }
201
202#ifdef SO_NOSIGPIPE
203 // Mac OS X does not have the MSG_NOSIGNAL flag. It does have this
204 // connections based version, however.
205 if (emitter.socketFileDescriptorEmitter > 0) {
206 int set_option = 1;
207 if (0 ==
208 setsockopt(emitter.socketFileDescriptorEmitter, SOL_SOCKET, SO_NOSIGPIPE, &set_option, sizeof(set_option))) {
209 }
210 else {
211 std::cout << "Failed to set socket signal option" << std::endl;
212 }
213 }
214#endif // SO_NOSIGPIPE
215
216#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
217 listen(emitter.socketFileDescriptorEmitter, static_cast<int>(max_clients));
218#else // Win32
219 listen(static_cast<unsigned int>(emitter.socketFileDescriptorEmitter), static_cast<int>(max_clients));
220#endif
221
222 std::cout << "Server ready" << std::endl;
223
224 started = true;
225
226 return true;
227}
228
236{
237 if (!started)
238 if (!start()) {
239 return false;
240 }
241
242 tv.tv_sec = tv_sec;
243#ifdef TARGET_OS_IPHONE
244 tv.tv_usec = static_cast<int>(tv_usec);
245#else
246 tv.tv_usec = tv_usec;
247#endif
248
249 FD_ZERO(&readFileDescriptor);
250
251 socketMax = emitter.socketFileDescriptorEmitter;
252 FD_SET(static_cast<unsigned int>(emitter.socketFileDescriptorEmitter), &readFileDescriptor);
253
254 for (unsigned int i = 0; i < receptor_list.size(); i++) {
255 FD_SET(static_cast<unsigned int>(receptor_list[i].socketFileDescriptorReceptor), &readFileDescriptor);
256
257 if (i == 0)
258 socketMax = receptor_list[i].socketFileDescriptorReceptor;
259
260 if (socketMax < receptor_list[i].socketFileDescriptorReceptor)
261 socketMax = receptor_list[i].socketFileDescriptorReceptor;
262 }
263
264 int value = select(static_cast<int>(socketMax) + 1, &readFileDescriptor, nullptr, nullptr, &tv);
265 if (value == -1) {
266 // vpERROR_TRACE( "vpServer::run(), select()" );
267 return false;
268 }
269 else if (value == 0) {
270 return false;
271 }
272 else {
273 if (FD_ISSET(static_cast<unsigned int>(emitter.socketFileDescriptorEmitter), &readFileDescriptor)) {
274 vpNetwork::vpReceptor client;
275 client.receptorAddressSize = sizeof(client.receptorAddress);
276#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
277 client.socketFileDescriptorReceptor = accept(
278 emitter.socketFileDescriptorEmitter, (struct sockaddr *)&client.receptorAddress, &client.receptorAddressSize);
279#else // Win32
280 client.socketFileDescriptorReceptor =
281 accept(static_cast<unsigned int>(emitter.socketFileDescriptorEmitter), (struct sockaddr *)&client.receptorAddress,
282 &client.receptorAddressSize);
283#endif
284
285#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
286 if ((client.socketFileDescriptorReceptor) == -1)
287#else
288 if ((client.socketFileDescriptorReceptor) == INVALID_SOCKET)
289#endif
290 vpERROR_TRACE("vpServer::run(), accept()");
291
292 client.receptorIP = inet_ntoa(client.receptorAddress.sin_addr);
293 printf("New client connected : %s\n", inet_ntoa(client.receptorAddress.sin_addr));
294 receptor_list.push_back(client);
295
296 return true;
297 }
298 else {
299 for (unsigned int i = 0; i < receptor_list.size(); i++) {
300 if (FD_ISSET(static_cast<unsigned int>(receptor_list[i].socketFileDescriptorReceptor), &readFileDescriptor)) {
301 char deco;
302#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
303 ssize_t numbytes = recv(receptor_list[i].socketFileDescriptorReceptor, &deco, 1, MSG_PEEK);
304#else // Win32
305 int numbytes = recv(static_cast<unsigned int>(receptor_list[i].socketFileDescriptorReceptor), &deco, 1, MSG_PEEK);
306#endif
307
308 if (numbytes == 0) {
309 std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
310 receptor_list.erase(receptor_list.begin() + static_cast<int>(i));
311 return 0;
312 }
313 }
314 }
315 }
316 }
317
318 return false;
319}
320
325END_VISP_NAMESPACE
326#elif !defined(VISP_BUILD_SHARED_LIBS)
327// Work around to avoid warning: libvisp_core.a(vpServer.cpp.o) has no symbols
328void dummy_vpServer() { }
329#endif
long tv_sec
Definition vpNetwork.h:167
int socketMax
Definition vpNetwork.h:150
fd_set readFileDescriptor
Definition vpNetwork.h:148
long tv_usec
Definition vpNetwork.h:168
std::vector< vpReceptor > receptor_list
Definition vpNetwork.h:147
struct timeval tv
Definition vpNetwork.h:166
vpEmitter emitter
Definition vpNetwork.h:146
void print(const char *id="")
bool start()
Definition vpServer.cpp:179
vpServer & operator=(const vpServer &server)
Copy operator.
Definition vpServer.cpp:93
virtual ~vpServer() VP_OVERRIDE
Definition vpServer.cpp:158
bool checkForConnections()
Definition vpServer.cpp:235
void print()
Definition vpServer.cpp:324
#define vpERROR_TRACE
Definition vpDebug.h:423