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