AsyncClient.h
Go to the documentation of this file.
1 /**************************************************************************************************
2  Software License Agreement (BSD License)
3 
4  Copyright (c) 2011-2013, LAR toolkit developers - University of Aveiro - http://lars.mec.ua.pt
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without modification, are permitted
8  provided that the following conditions are met:
9 
10  *Redistributions of source code must retain the above copyright notice, this list of
11  conditions and the following disclaimer.
12  *Redistributions in binary form must reproduce the above copyright notice, this list of
13  conditions and the following disclaimer in the documentation and/or other materials provided
14  with the distribution.
15  *Neither the name of the University of Aveiro nor the names of its contributors may be used to
16  endorse or promote products derived from this software without specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
19  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 ***************************************************************************************************/
27 #ifndef _ASYNC_CLIENT_H_
28 #define _ASYNC_CLIENT_H_
29 
35 #include <iostream>
36 #include <istream>
37 #include <ostream>
38 #include <string>
39 #include <boost/asio.hpp>
40 #include <boost/bind.hpp>
41 #include <boost/date_time/posix_time/posix_time.hpp>
42 #include <boost/signal.hpp>
43 #include <boost/thread/thread.hpp>
44 
45 using boost::asio::ip::tcp;
46 
47 using namespace std;
48 
55 {
56  public:
63  AsyncClient(boost::asio::io_service& io_service,const std::string& server, const std::string& port,std::string delimiter=std::string("\n")):
64  delimiter_(delimiter),
65  server_ip_(server),
66  server_port_(port),
67  query_(server_ip_,server_port_),
68  resolver_(io_service),
69  socket_(io_service)
70  {
71  attempting_connection_=false;
72  is_connected_=false;
73  error_ = boost::asio::error::not_connected;
74 
75  startConnection();
76  }
77 
84  {
85  socket_.close();
86  }
87 
95  {
96  if(attempting_connection_)
97  return;
98 
99  try
100  {
101  socket_.close();
102  }catch(std::exception& e)
103  {
104 // std::cout<<"Cannot close socket: "<<e.what()<<std::endl;
105  }
106 
107  attempting_connection_=true;
108 
109 
110  //Sets the established connection variable to false
111  is_connected_=false;
112 
113  //A small delay to avoid unnecessary taxation of the thread
114  boost::this_thread::sleep(boost::posix_time::milliseconds(50));
115 
116  //Stat the asynchronous resolver on the query object
117  resolver_.async_resolve(query_,boost::bind(&AsyncClient::handleResolve, this,boost::asio::placeholders::error,boost::asio::placeholders::iterator));
118  }
119 
125  bool isConnected(void)
126  {
127  return is_connected_;
128  }
129 
133  void close(void)
134  {
135  socket_.close();
136  error_ = boost::asio::error::not_connected;
137  is_connected_ = false;
138  }
139 
143  void reconnect(void)
144  {
145  //Attempt a new connection
146  startConnection();
147  }
148 
156  void write(std::string message)
157  {
158  if(!is_connected_)
159  throw boost::system::system_error(boost::asio::error::not_connected);
160 
161  std::ostream request_stream(&request_);
162  request_stream << message;
163  boost::asio::async_write(socket_,request_,boost::bind(&AsyncClient::writeRequestHandler, this,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
164  }
165 
167  boost::signal<void (std::string)> readHandler;
169  boost::signal<void (void)> writeHandler;
171  boost::signal<void (void)> connectHandler;
173  boost::system::error_code error_;
174 
175  private:
185  void writeRequestHandler(const boost::system::error_code& err,std::size_t bytes_transferred)
186  {
187  if(err)
188  {
189  //Connection is not established
190  is_connected_=false;
191  //Copy the error to the global variable
192  error_=err;
193 
194  attempting_connection_=false;
195 
196  //Attempt a new connection
197  startConnection();
198 
199  return;
200  }
201 
202  writeHandler();
203  }
204 
214  void handleResolve(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator)
215  {
216  //If there's a error start the process from the begin
217  if(err)
218  {
219  //Connection is not established
220  is_connected_=false;
221  //Copy the error to the global variable
222  error_=err;
223 
224  attempting_connection_=false;
225 
226  //Attempt a new connection
227  startConnection();
228 
229  return;
230  }
231 
232  // Attempt a connection to the first endpoint in the list. Each endpoint
233  // will be tried until we successfully establish a connection.
234  //Get the first endpoint of the list
235  tcp::endpoint endpoint = *endpoint_iterator;
236 
237  //Attempt a asynchronous connection to the first endpoint, the function handleConnect will try to connect to the rest of the endpoints if the connection fails on the first
238  socket_.async_connect(endpoint,boost::bind(&AsyncClient::handleConnect, this,boost::asio::placeholders::error, ++endpoint_iterator));
239  }
240 
250  void handleConnect(const boost::system::error_code& err,tcp::resolver::iterator endpoint_iterator)
251  {
252  //If this function was called after the connection was established do nothing
253  if(is_connected_)
254  return;
255 
256  //If there is no error
257  if (!err)
258  {
259  //Attempt to read data
260  startRead();
261 
262  //Copy the error to the global variable
263  error_=err;
264 
265  //Set the connection status to established
266  is_connected_=true;
267 
268  attempting_connection_=false;
269 
270  //Call the user successful connection handler
271  connectHandler();
272  }
273  else if (endpoint_iterator != tcp::resolver::iterator())
274  {
275  // The connection failed. Try the next endpoint in the list.
276 
277  //close the current socket
278  socket_.close();
279 
280  //Get the next endpoint
281  tcp::endpoint endpoint = *endpoint_iterator;
282  //Attempt a connect on the next endpoint, the current function is set has a the handler for the connection attempt
283  socket_.async_connect(endpoint,boost::bind(&AsyncClient::handleConnect,this,boost::asio::placeholders::error, ++endpoint_iterator));
284  }
285  else
286  {
287  //The list has no more endpoints
288 
289  //Set the connection status to not established
290  is_connected_=false;
291 
292  attempting_connection_=false;
293 
294  //Copy the error to the global variable
295  error_=err;
296 
297  if(error_ == boost::asio::error::operation_aborted || error_ == boost::asio::error::already_started)
298  error_=boost::asio::error::host_unreachable;
299 
300  //Attempt a new connection from the beginning
301  startConnection();
302  }
303  }
304 
311  void startRead(void)
312  {
313  // Start an asynchronous operation to read a newline-delimited message.
314  boost::asio::async_read_until(socket_,response_,delimiter_,boost::bind(&AsyncClient::handleRead,this,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
315  }
316 
327  void handleRead(const boost::system::error_code& err, std::size_t bytes_transferred)
328  {
329  //If there was some error on the operation
330  if(err)
331  {
332  //Set the connection status variable to false
333  is_connected_=false;
334 
335  //Copy the error to the global variable
336  error_ = err;
337 
338  attempting_connection_=false;
339 
340  //Attempt a new connection from the beginning
341  startConnection();
342 
343  return;
344  }
345 
346  //Create a istream from the streambuf
347  std::istream response_stream(&response_);
348  //Create a string variable
349  std::string line;
350  //Copy from the istream to the string variable
351  std::getline(response_stream, line);
352 
353  //Call the user read handler
354  readHandler(line);
355 
356  //Schedule a new read operation
357  startRead();
358  }
359 
361  std::string delimiter_;
362 
365 
368 
370  std::string server_ip_;
372  std::string server_port_;
373 
375  tcp::resolver::query query_;
376 
378  tcp::resolver resolver_;
380  tcp::socket socket_;
382  boost::asio::streambuf request_;
384  boost::asio::streambuf response_;
385 };
386 
387 #endif
bool attempting_connection_
Ongoing reconnection.
Definition: AsyncClient.h:367
tcp::resolver resolver_
Connection resolver, the resolver obtains the endpoints for the connection.
Definition: AsyncClient.h:378
void handleRead(const boost::system::error_code &err, std::size_t bytes_transferred)
New data handler.
Definition: AsyncClient.h:327
void startRead(void)
Start a read asynchronous operation.
Definition: AsyncClient.h:311
std::string server_ip_
Ip of the server.
Definition: AsyncClient.h:370
void reconnect(void)
Function to reestablish the connection.
Definition: AsyncClient.h:143
void handleConnect(const boost::system::error_code &err, tcp::resolver::iterator endpoint_iterator)
Handle a connection.
Definition: AsyncClient.h:250
bool isConnected(void)
Get the connection status.
Definition: AsyncClient.h:125
AsyncClient(boost::asio::io_service &io_service, const std::string &server, const std::string &port, std::string delimiter=std::string("\n"))
Class constructor.
Definition: AsyncClient.h:63
boost::system::error_code error_
Current error code of the communication.
Definition: AsyncClient.h:173
bool is_connected_
Connection status variable.
Definition: AsyncClient.h:364
void handleResolve(const boost::system::error_code &err, tcp::resolver::iterator endpoint_iterator)
Query resolve handler.
Definition: AsyncClient.h:214
std::string delimiter_
String used as delimiter in the read until function, default is \n.
Definition: AsyncClient.h:361
void write(std::string message)
Send a message to the server.
Definition: AsyncClient.h:156
boost::asio::streambuf request_
Stream buffer to hold the communications requests.
Definition: AsyncClient.h:382
tcp::resolver::query query_
Start an asynchronous resolve to translate the server and service names into a list of endpoints...
Definition: AsyncClient.h:375
boost::signal< void(void)> writeHandler
Successful writing handler.
Definition: AsyncClient.h:169
boost::signal< void(std::string)> readHandler
New data function handler.
Definition: AsyncClient.h:167
std::string server_port_
Port of the server.
Definition: AsyncClient.h:372
void startConnection()
Starts a query on the ip and port and starts the asynchronous resolver.
Definition: AsyncClient.h:94
boost::signal< void(void)> connectHandler
Successful connection establish handler.
Definition: AsyncClient.h:171
tcp::socket socket_
Connection socket variable.
Definition: AsyncClient.h:380
void writeRequestHandler(const boost::system::error_code &err, std::size_t bytes_transferred)
Write handler.
Definition: AsyncClient.h:185
Asynchronous tpc/ip communication object.
Definition: AsyncClient.h:54
void close(void)
Close the connection.
Definition: AsyncClient.h:133
~AsyncClient()
Class destructor.
Definition: AsyncClient.h:83
boost::asio::streambuf response_
Stream buffer to hold the communications responses.
Definition: AsyncClient.h:384


tcp_client
Author(s): Jorge Almeida
autogenerated on Mon Mar 2 2015 01:32:53