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