Visual Servoing Platform  version 3.6.1 under development (2024-12-17)
vpClient.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * TCP Client
32  */
33 
34 #include <visp3/core/vpConfig.h>
35 
36 // Specific case for UWP to introduce a workaround
37 // error C4996: 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
38 #if defined(WINRT) || defined(_WIN32)
39 #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
40 #define _WINSOCK_DEPRECATED_NO_WARNINGS
41 #endif
42 #endif
43 
44 // inet_ntop() not supported on win XP
45 #ifdef VISP_HAVE_FUNC_INET_NTOP
46 
47 #include <visp3/core/vpClient.h>
48 #include <visp3/core/vpDebug.h>
49 
50 BEGIN_VISP_NAMESPACE
51 vpClient::vpClient() : vpNetwork(), m_numberOfAttempts(0) { }
52 
57 
69 bool vpClient::connectToHostname(const std::string &hostname, const unsigned int &port_serv)
70 {
71  // get server host information from hostname
72  struct hostent *server = gethostbyname(hostname.c_str());
73 
74  if (server == nullptr) {
75  std::string noSuchHostMessage("ERROR, ");
76  noSuchHostMessage.append(hostname);
77  noSuchHostMessage.append(": no such host\n");
78  vpERROR_TRACE(noSuchHostMessage.c_str(), "vpClient::connectToHostname("
79  "const std::string &hostname, "
80  "const int &port_serv)");
81  return false;
82  }
83 
84  vpNetwork::vpReceptor serv;
85 
86  serv.socketFileDescriptorReceptor = socket(AF_INET, SOCK_STREAM, 0);
87 
88 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
89  if (serv.socketFileDescriptorReceptor < 0) {
90 #else
91  if (serv.socketFileDescriptorReceptor == INVALID_SOCKET) {
92 #endif
93  vpERROR_TRACE("ERROR opening socket", "vpClient::connectToHostname()");
94  return false;
95  }
96 
97  memset((char *)&serv.receptorAddress, '\0', sizeof(serv.receptorAddress));
98  serv.receptorAddress.sin_family = AF_INET;
99  memmove((char *)&serv.receptorAddress.sin_addr.s_addr, (char *)server->h_addr, (unsigned)server->h_length);
100  serv.receptorAddress.sin_port = htons((unsigned short)port_serv);
101  serv.receptorIP = inet_ntoa(*(in_addr *)server->h_addr);
102 
103  return connectServer(serv);
104  }
105 
116 bool vpClient::connectToIP(const std::string &ip, const unsigned int &port_serv)
117 {
118  vpNetwork::vpReceptor serv;
119 
120  serv.socketFileDescriptorReceptor = socket(AF_INET, SOCK_STREAM, 0);
121 
122 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
123  if (serv.socketFileDescriptorReceptor < 0) {
124 #else
125  if (serv.socketFileDescriptorReceptor == INVALID_SOCKET) {
126 #endif
127  vpERROR_TRACE("ERROR opening socket", "vpClient::connectToIP()");
128  return false;
129  }
130 
131  memset((char *)&serv.receptorAddress, '\0', sizeof(serv.receptorAddress));
132  serv.receptorAddress.sin_family = AF_INET;
133  serv.receptorAddress.sin_addr.s_addr = inet_addr(ip.c_str());
134  serv.receptorAddress.sin_port = htons((unsigned short)port_serv);
135 
136  return connectServer(serv);
137  }
138 
144 void vpClient::deconnect(const unsigned int &index)
145 {
146  if (index < receptor_list.size()) {
147 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
148  shutdown(receptor_list[index].socketFileDescriptorReceptor, SHUT_RDWR);
149 #else // _WIN32
150  shutdown(receptor_list[index].socketFileDescriptorReceptor, SD_BOTH);
151 #endif
152  receptor_list.erase(receptor_list.begin() + (int)index);
153  }
154 }
155 
160 {
161  for (unsigned int i = 0; i < receptor_list.size(); i++) {
162 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
163  shutdown(receptor_list[i].socketFileDescriptorReceptor, SHUT_RDWR);
164 #else // _WIN32
165  shutdown(receptor_list[i].socketFileDescriptorReceptor, SD_BOTH);
166 #endif
167  receptor_list.erase(receptor_list.begin() + (int)i);
168  i--;
169  }
170 }
171 
175 void vpClient::print() { vpNetwork::print("Server"); }
176 
177 // Private function
178 bool vpClient::connectServer(vpNetwork::vpReceptor &serv)
179 {
180  serv.receptorAddressSize = sizeof(serv.receptorAddress);
181 
182  m_numberOfAttempts = 15;
183  unsigned int ind = 1;
184  int connectionResult = -1;
185 
186  while (ind <= m_numberOfAttempts) {
187  std::cout << "Attempt number " << ind << "..." << std::endl;
188 
189  connectionResult =
190  connect(serv.socketFileDescriptorReceptor, (sockaddr *)&serv.receptorAddress, serv.receptorAddressSize);
191  if (connectionResult >= 0)
192  break;
193 
194  ind++;
195  vpTime::wait(1000);
196  }
197 
198  if (connectionResult < 0) {
199  vpERROR_TRACE("ERROR connecting, the server may not be waiting for "
200  "connection at this port.",
201  "vpClient::connectServer()");
202 
203  return false;
204  }
205 
206  receptor_list.push_back(serv);
207 
208 #ifdef SO_NOSIGPIPE
209  // Mac OS X does not have the MSG_NOSIGNAL flag. It does have this
210  // connections based version, however.
211  if (serv.socketFileDescriptorReceptor > 0) {
212  int set_option = 1;
213  if (0 == setsockopt(serv.socketFileDescriptorReceptor, SOL_SOCKET, SO_NOSIGPIPE, &set_option, sizeof(set_option))) {
214  }
215  else {
216  std::cout << "Failed to set socket signal option" << std::endl;
217  }
218  }
219 #endif // SO_NOSIGPIPE
220 
221  std::cout << "Connected!" << std::endl;
222  return true;
223 }
224 END_VISP_NAMESPACE
225 #elif !defined(VISP_BUILD_SHARED_LIBS)
226 // Work around to avoid warning: libvisp_core.a(vpClient.cpp.o) has no symbols
227 void dummy_vpClient() { };
228 #endif
void print()
Definition: vpClient.cpp:175
vpClient()
Definition: vpClient.cpp:51
bool connectToIP(const std::string &ip, const unsigned int &port_serv)
Definition: vpClient.cpp:116
bool connectToHostname(const std::string &hostname, const unsigned int &port_serv)
Definition: vpClient.cpp:69
virtual ~vpClient() VP_OVERRIDE
Definition: vpClient.cpp:56
void deconnect(const unsigned int &index=0)
Definition: vpClient.cpp:144
void stop()
Definition: vpClient.cpp:159
This class represents a Transmission Control Protocol (TCP) network.
Definition: vpNetwork.h:96
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:137
void print(const char *id="")
Definition: vpNetwork.cpp:129
VISP_EXPORT int wait(double t0, double t)