Visual Servoing Platform  version 3.6.1 under development (2024-12-17)
vpServer.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 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 
56 BEGIN_VISP_NAMESPACE
60 vpServer::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 
85 vpServer::vpServer(const int &port_serv) : adress(), port(0), started(false), max_clients(10)
86 {
87  int protocol = 0;
88  emitter.socketFileDescriptorEmitter = socket(AF_INET, SOCK_STREAM, protocol);
89 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
90  if (emitter.socketFileDescriptorEmitter < 0)
91 #else
92  if (emitter.socketFileDescriptorEmitter == INVALID_SOCKET)
93 #endif
94  {
95  vpERROR_TRACE("vpServer::vpServer(const int &port_serv), cannot open socket.");
96  }
97  emitter.emitterAddress.sin_family = AF_INET;
98  emitter.emitterAddress.sin_addr.s_addr = INADDR_ANY; // inet_addr("127.0.0.1");;
99  emitter.emitterAddress.sin_port = htons((unsigned short)port_serv);
100 
101  adress = inet_ntoa(emitter.emitterAddress.sin_addr);
102  port = port_serv;
103 }
104 
111 vpServer::vpServer(const std::string &adress_serv, const int &port_serv)
112  : adress(), port(0), started(false), max_clients(10)
113 {
114  int protocol = 0;
115  emitter.socketFileDescriptorEmitter = socket(AF_INET, SOCK_STREAM, protocol);
116 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
117  if (emitter.socketFileDescriptorEmitter < 0)
118 #else
119  if (emitter.socketFileDescriptorEmitter == INVALID_SOCKET)
120 #endif
121  {
122  vpERROR_TRACE("vpServer::vpServer(const std::string &adress_serv,const "
123  "int &port_serv), cannot open socket.");
124  }
125  emitter.emitterAddress.sin_family = AF_INET;
126  emitter.emitterAddress.sin_addr.s_addr = inet_addr(adress_serv.c_str());
127  emitter.emitterAddress.sin_port = htons((unsigned short)port_serv);
128 
129  adress = adress_serv;
130  port = port_serv;
131 }
132 
137 {
138 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
139  close(emitter.socketFileDescriptorEmitter);
140 #else // Win32
141  closesocket((unsigned)emitter.socketFileDescriptorEmitter);
142 #endif
143 
144  for (unsigned int i = 0; i < receptor_list.size(); i++)
145 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
146  close(receptor_list[i].socketFileDescriptorReceptor);
147 #else // Win32
148  closesocket((unsigned)receptor_list[i].socketFileDescriptorReceptor);
149 #endif
150 }
151 
158 {
159  int serverStructLength = sizeof(emitter.emitterAddress);
160 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
161  int bindResult = bind(emitter.socketFileDescriptorEmitter, (struct sockaddr *)&emitter.emitterAddress,
162  (unsigned)serverStructLength);
163 #else // Win32
164  int bindResult = bind((unsigned)emitter.socketFileDescriptorEmitter, (struct sockaddr *)&emitter.emitterAddress,
165  serverStructLength);
166 #endif
167 
168  if (bindResult < 0) {
169  std::cout << "Error id : " << bindResult << std::endl;
170  std::stringstream errorMessage;
171  errorMessage << "vpServer::vpServer(), cannot bind to port";
172  errorMessage << " ";
173  errorMessage << port;
174  errorMessage << " The port may be already used.";
175 
176  vpERROR_TRACE(errorMessage.str().c_str());
177  return false;
178  }
179 
180 #ifdef SO_NOSIGPIPE
181  // Mac OS X does not have the MSG_NOSIGNAL flag. It does have this
182  // connections based version, however.
183  if (emitter.socketFileDescriptorEmitter > 0) {
184  int set_option = 1;
185  if (0 ==
186  setsockopt(emitter.socketFileDescriptorEmitter, SOL_SOCKET, SO_NOSIGPIPE, &set_option, sizeof(set_option))) {
187  }
188  else {
189  std::cout << "Failed to set socket signal option" << std::endl;
190  }
191  }
192 #endif // SO_NOSIGPIPE
193 
194 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
195  listen(emitter.socketFileDescriptorEmitter, (int)max_clients);
196 #else // Win32
197  listen((unsigned)emitter.socketFileDescriptorEmitter, (int)max_clients);
198 #endif
199 
200  std::cout << "Server ready" << std::endl;
201 
202  started = true;
203 
204  return true;
205 }
206 
214 {
215  if (!started)
216  if (!start()) {
217  return false;
218  }
219 
220  tv.tv_sec = tv_sec;
221 #ifdef TARGET_OS_IPHONE
222  tv.tv_usec = (int)tv_usec;
223 #else
224  tv.tv_usec = tv_usec;
225 #endif
226 
227  FD_ZERO(&readFileDescriptor);
228 
229  socketMax = emitter.socketFileDescriptorEmitter;
230  FD_SET((unsigned)emitter.socketFileDescriptorEmitter, &readFileDescriptor);
231 
232  for (unsigned int i = 0; i < receptor_list.size(); i++) {
233  FD_SET((unsigned)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor);
234 
235  if (i == 0)
236  socketMax = receptor_list[i].socketFileDescriptorReceptor;
237 
238  if (socketMax < receptor_list[i].socketFileDescriptorReceptor)
239  socketMax = receptor_list[i].socketFileDescriptorReceptor;
240  }
241 
242  int value = select((int)socketMax + 1, &readFileDescriptor, nullptr, nullptr, &tv);
243  if (value == -1) {
244  // vpERROR_TRACE( "vpServer::run(), select()" );
245  return false;
246  }
247  else if (value == 0) {
248  return false;
249  }
250  else {
251  if (FD_ISSET((unsigned int)emitter.socketFileDescriptorEmitter, &readFileDescriptor)) {
252  vpNetwork::vpReceptor client;
253  client.receptorAddressSize = sizeof(client.receptorAddress);
254 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
255  client.socketFileDescriptorReceptor = accept(
256  emitter.socketFileDescriptorEmitter, (struct sockaddr *)&client.receptorAddress, &client.receptorAddressSize);
257 #else // Win32
258  client.socketFileDescriptorReceptor =
259  accept((unsigned int)emitter.socketFileDescriptorEmitter, (struct sockaddr *)&client.receptorAddress,
260  &client.receptorAddressSize);
261 #endif
262 
263 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
264  if ((client.socketFileDescriptorReceptor) == -1)
265 #else
266  if ((client.socketFileDescriptorReceptor) == INVALID_SOCKET)
267 #endif
268  vpERROR_TRACE("vpServer::run(), accept()");
269 
270  client.receptorIP = inet_ntoa(client.receptorAddress.sin_addr);
271  printf("New client connected : %s\n", inet_ntoa(client.receptorAddress.sin_addr));
272  receptor_list.push_back(client);
273 
274  return true;
275  }
276  else {
277  for (unsigned int i = 0; i < receptor_list.size(); i++) {
278  if (FD_ISSET((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor)) {
279  char deco;
280 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
281  ssize_t numbytes = recv(receptor_list[i].socketFileDescriptorReceptor, &deco, 1, MSG_PEEK);
282 #else // Win32
283  int numbytes = recv((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &deco, 1, MSG_PEEK);
284 #endif
285 
286  if (numbytes == 0) {
287  std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
288  receptor_list.erase(receptor_list.begin() + (int)i);
289  return 0;
290  }
291  }
292  }
293  }
294  }
295 
296  return false;
297 }
298 
302 void vpServer::print() { vpNetwork::print("Client"); }
303 END_VISP_NAMESPACE
304 #elif !defined(VISP_BUILD_SHARED_LIBS)
305 // Work around to avoid warning: libvisp_core.a(vpServer.cpp.o) has no symbols
306 void dummy_vpServer() { };
307 #endif
long tv_sec
Definition: vpNetwork.h:157
fd_set readFileDescriptor
Definition: vpNetwork.h:138
long tv_usec
Definition: vpNetwork.h:158
SOCKET socketMax
Definition: vpNetwork.h:142
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:137
struct timeval tv
Definition: vpNetwork.h:156
vpEmitter emitter
Definition: vpNetwork.h:136
void print(const char *id="")
Definition: vpNetwork.cpp:129
vpServer()
Definition: vpServer.cpp:60
bool start()
Definition: vpServer.cpp:157
virtual ~vpServer() VP_OVERRIDE
Definition: vpServer.cpp:136
bool checkForConnections()
Definition: vpServer.cpp:213
void print()
Definition: vpServer.cpp:302