Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
vpClient.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 Client
33  *
34  * Authors:
35  * Aurelien Yol
36  *
37 *****************************************************************************/
38 
39 #include <visp3/core/vpClient.h>
40 
41 // inet_ntop() not supported on win XP
42 #ifdef VISP_HAVE_FUNC_INET_NTOP
43 
44 #include <visp3/core/vpDebug.h>
45 
47 vpClient::vpClient() : vpNetwork(), m_numberOfAttempts(0) { }
48 
53 
65 bool vpClient::connectToHostname(const std::string &hostname, const unsigned int &port_serv)
66 {
67  // get server host information from hostname
68  struct hostent *server = gethostbyname(hostname.c_str());
69 
70  if (server == nullptr) {
71  std::string noSuchHostMessage("ERROR, ");
72  noSuchHostMessage.append(hostname);
73  noSuchHostMessage.append(": no such host\n");
74  vpERROR_TRACE(noSuchHostMessage.c_str(), "vpClient::connectToHostname("
75  "const std::string &hostname, "
76  "const int &port_serv)");
77  return false;
78  }
79 
80  vpNetwork::vpReceptor serv;
81 
82  serv.socketFileDescriptorReceptor = socket(AF_INET, SOCK_STREAM, 0);
83 
84 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
85  if (serv.socketFileDescriptorReceptor < 0) {
86 #else
87  if (serv.socketFileDescriptorReceptor == INVALID_SOCKET) {
88 #endif
89  vpERROR_TRACE("ERROR opening socket", "vpClient::connectToHostname()");
90  return false;
91  }
92 
93  memset((char *)&serv.receptorAddress, '\0', sizeof(serv.receptorAddress));
94  serv.receptorAddress.sin_family = AF_INET;
95  memmove((char *)&serv.receptorAddress.sin_addr.s_addr, (char *)server->h_addr, (unsigned)server->h_length);
96  serv.receptorAddress.sin_port = htons((unsigned short)port_serv);
97  serv.receptorIP = inet_ntoa(*(in_addr *)server->h_addr);
98 
99  return connectServer(serv);
100 }
101 
112 bool vpClient::connectToIP(const std::string &ip, const unsigned int &port_serv)
113 {
114  vpNetwork::vpReceptor serv;
115 
116  serv.socketFileDescriptorReceptor = socket(AF_INET, SOCK_STREAM, 0);
117 
118 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
119  if (serv.socketFileDescriptorReceptor < 0) {
120 #else
121  if (serv.socketFileDescriptorReceptor == INVALID_SOCKET) {
122 #endif
123  vpERROR_TRACE("ERROR opening socket", "vpClient::connectToIP()");
124  return false;
125  }
126 
127  memset((char *)&serv.receptorAddress, '\0', sizeof(serv.receptorAddress));
128  serv.receptorAddress.sin_family = AF_INET;
129  serv.receptorAddress.sin_addr.s_addr = inet_addr(ip.c_str());
130  serv.receptorAddress.sin_port = htons((unsigned short)port_serv);
131 
132  return connectServer(serv);
133 }
134 
140 void vpClient::deconnect(const unsigned int &index)
141 {
142  if (index < receptor_list.size()) {
143 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
144  shutdown(receptor_list[index].socketFileDescriptorReceptor, SHUT_RDWR);
145 #else // _WIN32
146  shutdown(receptor_list[index].socketFileDescriptorReceptor, SD_BOTH);
147 #endif
148  receptor_list.erase(receptor_list.begin() + (int)index);
149  }
150 }
151 
156 {
157  for (unsigned int i = 0; i < receptor_list.size(); i++) {
158 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
159  shutdown(receptor_list[i].socketFileDescriptorReceptor, SHUT_RDWR);
160 #else // _WIN32
161  shutdown(receptor_list[i].socketFileDescriptorReceptor, SD_BOTH);
162 #endif
163  receptor_list.erase(receptor_list.begin() + (int)i);
164  i--;
165  }
166 }
167 
171 void vpClient::print() { vpNetwork::print("Server"); }
172 
173 // Private function
174 bool vpClient::connectServer(vpNetwork::vpReceptor &serv)
175 {
176  serv.receptorAddressSize = sizeof(serv.receptorAddress);
177 
178  m_numberOfAttempts = 15;
179  unsigned int ind = 1;
180  int connectionResult = -1;
181 
182  while (ind <= m_numberOfAttempts) {
183  std::cout << "Attempt number " << ind << "..." << std::endl;
184 
185  connectionResult =
186  connect(serv.socketFileDescriptorReceptor, (sockaddr *)&serv.receptorAddress, serv.receptorAddressSize);
187  if (connectionResult >= 0)
188  break;
189 
190  ind++;
191  vpTime::wait(1000);
192  }
193 
194  if (connectionResult < 0) {
195  vpERROR_TRACE("ERROR connecting, the server may not be waiting for "
196  "connection at this port.",
197  "vpClient::connectServer()");
198 
199  return false;
200  }
201 
202  receptor_list.push_back(serv);
203 
204 #ifdef SO_NOSIGPIPE
205  // Mac OS X does not have the MSG_NOSIGNAL flag. It does have this
206  // connections based version, however.
207  if (serv.socketFileDescriptorReceptor > 0) {
208  int set_option = 1;
209  if (0 == setsockopt(serv.socketFileDescriptorReceptor, SOL_SOCKET, SO_NOSIGPIPE, &set_option, sizeof(set_option))) {
210  }
211  else {
212  std::cout << "Failed to set socket signal option" << std::endl;
213  }
214  }
215 #endif // SO_NOSIGPIPE
216 
217  std::cout << "Connected!" << std::endl;
218  return true;
219 }
220 END_VISP_NAMESPACE
221 #elif !defined(VISP_BUILD_SHARED_LIBS)
222 // Work around to avoid warning: libvisp_core.a(vpClient.cpp.o) has no symbols
223 void dummy_vpClient() { };
224 #endif
void print()
Definition: vpClient.cpp:171
vpClient()
Definition: vpClient.cpp:47
bool connectToIP(const std::string &ip, const unsigned int &port_serv)
Definition: vpClient.cpp:112
bool connectToHostname(const std::string &hostname, const unsigned int &port_serv)
Definition: vpClient.cpp:65
virtual ~vpClient() VP_OVERRIDE
Definition: vpClient.cpp:52
void deconnect(const unsigned int &index=0)
Definition: vpClient.cpp:140
void stop()
Definition: vpClient.cpp:155
This class represents a Transmission Control Protocol (TCP) network.
Definition: vpNetwork.h:88
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:129
void print(const char *id="")
Definition: vpNetwork.cpp:125
#define vpERROR_TRACE
Definition: vpDebug.h:409
VISP_EXPORT int wait(double t0, double t)