client_socket.cpp
Go to the documentation of this file.
1 /*
2  * @brief client_socket encapsulates connecting, closing and setting socket options
3  * for tcp client sockets.
4  *
5  * Copyright (C) 2019 Ing.-Buero Dr. Michael Lehning, Hildesheim
6  * Copyright (C) 2019 SICK AG, Waldkirch
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * All rights reserved.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions are met:
24  *
25  * * Redistributions of source code must retain the above copyright
26  * notice, this list of conditions and the following disclaimer.
27  * * Redistributions in binary form must reproduce the above copyright
28  * notice, this list of conditions and the following disclaimer in the
29  * documentation and/or other materials provided with the distribution.
30  * * Neither the name of SICK AG nor the names of its
31  * contributors may be used to endorse or promote products derived from
32  * this software without specific prior written permission
33  * * Neither the name of Ing.-Buero Dr. Michael Lehning nor the names of its
34  * contributors may be used to endorse or promote products derived from
35  * this software without specific prior written permission
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
38  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
41  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
44  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
45  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47  * POSSIBILITY OF SUCH DAMAGE.
48  *
49  * Authors:
50  * Michael Lehning <michael.lehning@lehning.de>
51  *
52  * Copyright 2019 SICK AG
53  * Copyright 2019 Ing.-Buero Dr. Michael Lehning
54  *
55  */
56 #ifndef _MSC_VER
57 #include <netdb.h>
58 #endif
59 #include "sick_scan/ros_wrapper.h"
60 
62 
67 {
68 }
69 
74 {
75  close();
76 }
77 
84 bool sick_scan_xd::ClientSocket::connect(const std::string & server_address, int tcp_port)
85 {
86  try
87  {
88  // Connect to server
89  m_tcp_socket = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
90  if( m_tcp_socket == INVALID_SOCKET )
91  {
92  ROS_ERROR_STREAM("## ERROR ClientSocket::connect(" << server_address << ":" << tcp_port << "): can't create socket");
93  return false;
94  }
95 
96  struct sockaddr_in addr;
97  struct hostent *server;
98  server = gethostbyname(server_address.c_str());
99  memset(&addr, 0, sizeof(addr)); // Zero out structure
100  addr.sin_family = AF_INET;
101  #ifdef _MSC_VER
102  memcpy((char *)&addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
103  #else
104  bcopy((char *)server->h_addr, (char *)&addr.sin_addr.s_addr, server->h_length);
105  #endif
106  addr.sin_port = htons(tcp_port); // Host-2-Network byte order
107  if (::connect(m_tcp_socket, (sockaddr*)(&addr), sizeof(addr)) < 0)
108  {
109  ROS_ERROR_STREAM("## ERROR ClientSocket::connect(" << server_address << ":" << tcp_port << "): connect failed");
110  return false;
111  }
112 
113  /* Get and set options for client sockets
114  boost::system::error_code socket_option_errorcodes[3];
115  boost::asio::ip::tcp::no_delay socket_option_no_delay;
116  boost::asio::socket_base::send_buffer_size socket_option_send_buffer_size;
117  boost::asio::socket_base::receive_buffer_size socket_option_receive_buffer_size;
118 
119  m_tcp_socket.get_option(socket_option_no_delay, socket_option_errorcodes[0]);
120  m_tcp_socket.get_option(socket_option_send_buffer_size, socket_option_errorcodes[1]);
121  m_tcp_socket.get_option(socket_option_receive_buffer_size, socket_option_errorcodes[2]);
122 
123  if (socket_option_errorcodes[0] || socket_option_no_delay.value() == false)
124  m_tcp_socket.set_option(boost::asio::ip::tcp::no_delay(true), socket_option_errorcodes[0]);
125  if (socket_option_errorcodes[1] || socket_option_send_buffer_size.value() < 64 * 1024)
126  m_tcp_socket.set_option(boost::asio::socket_base::send_buffer_size(64 * 1024), socket_option_errorcodes[1]);
127  if (socket_option_errorcodes[2] || socket_option_receive_buffer_size.value() < 64 * 1024)
128  m_tcp_socket.set_option(boost::asio::socket_base::receive_buffer_size(64 * 1024), socket_option_errorcodes[2]);
129 
130  m_tcp_socket.get_option(socket_option_no_delay, socket_option_errorcodes[0]);
131  m_tcp_socket.get_option(socket_option_send_buffer_size, socket_option_errorcodes[1]);
132  m_tcp_socket.get_option(socket_option_receive_buffer_size, socket_option_errorcodes[2]);
133 
134  if(socket_option_errorcodes[0] || socket_option_errorcodes[1] || socket_option_errorcodes[2])
135  {
136  ROS_WARN_STREAM("## ClientSocket::connect(): socket connected to " << server_address << ":" << tcp_port << ", but socket::get_option() failed, "
137  << " socket options error messages: no_delay=" << socket_option_errorcodes[0].message() << ", send_buffer_size=" << socket_option_errorcodes[1].message()
138  << ", receive_buffer_size=" << socket_option_errorcodes[2].message());
139  }
140  ROS_INFO_STREAM("ClientSocket::connect(): socket connected to " << server_address << ":" << tcp_port << ", socket options values: no_delay=" << socket_option_no_delay.value()
141  << ", send_buffer_size=" << socket_option_send_buffer_size.value() << ", receive_buffer_size=" << socket_option_receive_buffer_size.value());
142  */
143  return true;
144  }
145  catch(std::exception & exc)
146  {
147  ROS_WARN_STREAM("## ERROR ClientSocket::connect(): connect to " << server_address << ":" << tcp_port << " failed, exception " << exc.what());
148  }
149  return false;
150 }
151 
158 bool sick_scan_xd::ClientSocket::close(bool force_shutdown)
159 {
160  try
161  {
162 #ifdef _MSC_VER
163  closesocket(m_tcp_socket);
164 #else
165  ::close(m_tcp_socket);
166 #endif
167  return true;
168  }
169  catch(std::exception & exc)
170  {
171  ROS_WARN_STREAM("ColaTransmitter::closeTcpConnections(): exception " << exc.what() << " on closing connection.");
172  }
173  return false;
174 }
sick_scan_xd::ClientSocket::~ClientSocket
virtual ~ClientSocket()
Definition: client_socket.cpp:73
sick_scan_xd::ClientSocket::ClientSocket
ClientSocket()
Definition: client_socket.cpp:66
client_socket.h
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
Definition: sick_scan_logging.h:123
sick_scan_xd::ClientSocket::close
virtual bool close(bool force_shutdown=false)
Definition: client_socket.cpp:158
netdb.h
test_server.tcp_port
int tcp_port
Definition: test_server.py:204
closesocket
#define closesocket
Definition: udp_sockets.h:85
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(...)
Definition: sick_scan_ros2_example.cpp:72
sick_scan_xd::ClientSocket::connect
virtual bool connect(const std::string &server_address, int tcp_port)
Definition: client_socket.cpp:84
ros_wrapper.h
test_server.server
server
Definition: test_server.py:219
INVALID_SOCKET
#define INVALID_SOCKET
Definition: udp_sockets.h:83


sick_scan_xd
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Fri Oct 25 2024 02:47:07