Visual Servoing Platform  version 3.6.1 under development (2024-04-25)
vpServer.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  * TCP Server
33  *
34 *****************************************************************************/
35 
36 #include <visp3/core/vpServer.h>
37 
38 #include <sstream>
39 
40 // inet_ntop() not supported on win XP
41 #ifdef VISP_HAVE_FUNC_INET_NTOP
42 
43 #if defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
44 #include <TargetConditionals.h> // To detect OSX or IOS using TARGET_OS_IPHONE or TARGET_OS_IOS macro
45 #endif
46 
50 vpServer::vpServer() : adress(), port(0), started(false), max_clients(10)
51 {
52  int protocol = 0;
53  emitter.socketFileDescriptorEmitter = socket(AF_INET, SOCK_STREAM, protocol);
54 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
55  if (emitter.socketFileDescriptorEmitter < 0)
56 #else
57  if (emitter.socketFileDescriptorEmitter == INVALID_SOCKET)
58 #endif
59  {
60  vpERROR_TRACE("vpServer::vpServer(), cannot open socket.");
61  }
62  emitter.emitterAddress.sin_family = AF_INET;
63  emitter.emitterAddress.sin_addr.s_addr = INADDR_ANY;
64  emitter.emitterAddress.sin_port = 0;
65 
66  adress = inet_ntoa(emitter.emitterAddress.sin_addr);
67  port = emitter.emitterAddress.sin_port;
68 }
69 
75 vpServer::vpServer(const int &port_serv) : adress(), port(0), started(false), max_clients(10)
76 {
77  int protocol = 0;
78  emitter.socketFileDescriptorEmitter = socket(AF_INET, SOCK_STREAM, protocol);
79 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
80  if (emitter.socketFileDescriptorEmitter < 0)
81 #else
82  if (emitter.socketFileDescriptorEmitter == INVALID_SOCKET)
83 #endif
84  {
85  vpERROR_TRACE("vpServer::vpServer(const int &port_serv), cannot open socket.");
86  }
87  emitter.emitterAddress.sin_family = AF_INET;
88  emitter.emitterAddress.sin_addr.s_addr = INADDR_ANY; // inet_addr("127.0.0.1");;
89  emitter.emitterAddress.sin_port = htons((unsigned short)port_serv);
90 
91  adress = inet_ntoa(emitter.emitterAddress.sin_addr);
92  port = port_serv;
93 }
94 
101 vpServer::vpServer(const std::string &adress_serv, const int &port_serv)
102  : adress(), port(0), started(false), max_clients(10)
103 {
104  int protocol = 0;
105  emitter.socketFileDescriptorEmitter = socket(AF_INET, SOCK_STREAM, protocol);
106 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
107  if (emitter.socketFileDescriptorEmitter < 0)
108 #else
109  if (emitter.socketFileDescriptorEmitter == INVALID_SOCKET)
110 #endif
111  {
112  vpERROR_TRACE("vpServer::vpServer(const std::string &adress_serv,const "
113  "int &port_serv), cannot open socket.");
114  }
115  emitter.emitterAddress.sin_family = AF_INET;
116  emitter.emitterAddress.sin_addr.s_addr = inet_addr(adress_serv.c_str());
117  emitter.emitterAddress.sin_port = htons((unsigned short)port_serv);
118 
119  adress = adress_serv;
120  port = port_serv;
121 }
122 
127 {
128 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
129  close(emitter.socketFileDescriptorEmitter);
130 #else // Win32
131  closesocket((unsigned)emitter.socketFileDescriptorEmitter);
132 #endif
133 
134  for (unsigned int i = 0; i < receptor_list.size(); i++)
135 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
136  close(receptor_list[i].socketFileDescriptorReceptor);
137 #else // Win32
138  closesocket((unsigned)receptor_list[i].socketFileDescriptorReceptor);
139 #endif
140 }
141 
148 {
149  int serverStructLength = sizeof(emitter.emitterAddress);
150 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
151  int bindResult = bind(emitter.socketFileDescriptorEmitter, (struct sockaddr *)&emitter.emitterAddress,
152  (unsigned)serverStructLength);
153 #else // Win32
154  int bindResult = bind((unsigned)emitter.socketFileDescriptorEmitter, (struct sockaddr *)&emitter.emitterAddress,
155  serverStructLength);
156 #endif
157 
158  if (bindResult < 0) {
159  std::cout << "Error id : " << bindResult << std::endl;
160  std::stringstream errorMessage;
161  errorMessage << "vpServer::vpServer(), cannot bind to port";
162  errorMessage << " ";
163  errorMessage << port;
164  errorMessage << " The port may be already used.";
165 
166  vpERROR_TRACE(errorMessage.str().c_str());
167  return false;
168  }
169 
170 #ifdef SO_NOSIGPIPE
171  // Mac OS X does not have the MSG_NOSIGNAL flag. It does have this
172  // connections based version, however.
173  if (emitter.socketFileDescriptorEmitter > 0) {
174  int set_option = 1;
175  if (0 ==
176  setsockopt(emitter.socketFileDescriptorEmitter, SOL_SOCKET, SO_NOSIGPIPE, &set_option, sizeof(set_option))) {
177  } else {
178  std::cout << "Failed to set socket signal option" << std::endl;
179  }
180  }
181 #endif // SO_NOSIGPIPE
182 
183 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
184  listen(emitter.socketFileDescriptorEmitter, (int)max_clients);
185 #else // Win32
186  listen((unsigned)emitter.socketFileDescriptorEmitter, (int)max_clients);
187 #endif
188 
189  std::cout << "Server ready" << std::endl;
190 
191  started = true;
192 
193  return true;
194 }
195 
203 {
204  if (!started)
205  if (!start()) {
206  return false;
207  }
208 
209  tv.tv_sec = tv_sec;
210 #ifdef TARGET_OS_IPHONE
211  tv.tv_usec = (int)tv_usec;
212 #else
213  tv.tv_usec = tv_usec;
214 #endif
215 
216  FD_ZERO(&readFileDescriptor);
217 
218  socketMax = emitter.socketFileDescriptorEmitter;
219  FD_SET((unsigned)emitter.socketFileDescriptorEmitter, &readFileDescriptor);
220 
221  for (unsigned int i = 0; i < receptor_list.size(); i++) {
222  FD_SET((unsigned)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor);
223 
224  if (i == 0)
225  socketMax = receptor_list[i].socketFileDescriptorReceptor;
226 
227  if (socketMax < receptor_list[i].socketFileDescriptorReceptor)
228  socketMax = receptor_list[i].socketFileDescriptorReceptor;
229  }
230 
231  int value = select((int)socketMax + 1, &readFileDescriptor, nullptr, nullptr, &tv);
232  if (value == -1) {
233  // vpERROR_TRACE( "vpServer::run(), select()" );
234  return false;
235  } else if (value == 0) {
236  return false;
237  } else {
238  if (FD_ISSET((unsigned int)emitter.socketFileDescriptorEmitter, &readFileDescriptor)) {
239  vpNetwork::vpReceptor client;
240  client.receptorAddressSize = sizeof(client.receptorAddress);
241 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
242  client.socketFileDescriptorReceptor = accept(
243  emitter.socketFileDescriptorEmitter, (struct sockaddr *)&client.receptorAddress, &client.receptorAddressSize);
244 #else // Win32
245  client.socketFileDescriptorReceptor =
246  accept((unsigned int)emitter.socketFileDescriptorEmitter, (struct sockaddr *)&client.receptorAddress,
247  &client.receptorAddressSize);
248 #endif
249 
250 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
251  if ((client.socketFileDescriptorReceptor) == -1)
252 #else
253  if ((client.socketFileDescriptorReceptor) == INVALID_SOCKET)
254 #endif
255  vpERROR_TRACE("vpServer::run(), accept()");
256 
257  client.receptorIP = inet_ntoa(client.receptorAddress.sin_addr);
258  printf("New client connected : %s\n", inet_ntoa(client.receptorAddress.sin_addr));
259  receptor_list.push_back(client);
260 
261  return true;
262  } else {
263  for (unsigned int i = 0; i < receptor_list.size(); i++) {
264  if (FD_ISSET((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor)) {
265  char deco;
266 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
267  ssize_t numbytes = recv(receptor_list[i].socketFileDescriptorReceptor, &deco, 1, MSG_PEEK);
268 #else // Win32
269  int numbytes = recv((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &deco, 1, MSG_PEEK);
270 #endif
271 
272  if (numbytes == 0) {
273  std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
274  receptor_list.erase(receptor_list.begin() + (int)i);
275  return 0;
276  }
277  }
278  }
279  }
280  }
281 
282  return false;
283 }
284 
288 void vpServer::print() { vpNetwork::print("Client"); }
289 
290 #elif !defined(VISP_BUILD_SHARED_LIBS)
291 // Work around to avoid warning: libvisp_core.a(vpServer.cpp.o) has no symbols
292 void dummy_vpServer(){};
293 #endif
long tv_sec
Definition: vpNetwork.h:147
int socketMax
Definition: vpNetwork.h:130
fd_set readFileDescriptor
Definition: vpNetwork.h:128
long tv_usec
Definition: vpNetwork.h:148
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:127
struct timeval tv
Definition: vpNetwork.h:146
vpEmitter emitter
Definition: vpNetwork.h:126
void print(const char *id="")
Definition: vpNetwork.cpp:123
vpServer()
Definition: vpServer.cpp:50
bool start()
Definition: vpServer.cpp:147
bool checkForConnections()
Definition: vpServer.cpp:202
void print()
Definition: vpServer.cpp:288
virtual ~vpServer() vp_override
Definition: vpServer.cpp:126
#define vpERROR_TRACE
Definition: vpDebug.h:382