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