Visual Servoing Platform version 3.5.0
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
51vpServer::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
76vpServer::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
102vpServer::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
290
291#elif !defined(VISP_BUILD_SHARED_LIBS)
292// Work arround to avoid warning: libvisp_core.a(vpServer.cpp.o) has no symbols
293void dummy_vpServer(){};
294#endif
long tv_sec
Definition: vpNetwork.h:150
int socketMax
Definition: vpNetwork.h:133
fd_set readFileDescriptor
Definition: vpNetwork.h:131
long tv_usec
Definition: vpNetwork.h:151
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:130
struct timeval tv
Definition: vpNetwork.h:149
vpEmitter emitter
Definition: vpNetwork.h:129
void print(const char *id="")
Definition: vpNetwork.cpp:123
vpServer()
Definition: vpServer.cpp:51
virtual ~vpServer()
Definition: vpServer.cpp:127
bool start()
Definition: vpServer.cpp:148
bool checkForConnections()
Definition: vpServer.cpp:203
void print()
Definition: vpServer.cpp:289
#define vpERROR_TRACE
Definition: vpDebug.h:393