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