FACT++  1.0
fsc.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <string>
3 #include <boost/asio.hpp>
4 #include <boost/bind.hpp>
5 #include <boost/lexical_cast.hpp>
6 #include <boost/asio/deadline_timer.hpp>
7 #include <boost/enable_shared_from_this.hpp>
8 
9 using boost::lexical_cast;
10 
11 #include "Time.h"
12 
13 #include "HeadersFTM.h"
14 
15 using namespace std;
16 using namespace FTM;
17 
18 namespace ba = boost::asio;
19 namespace bs = boost::system;
20 namespace dummy = ba::placeholders;
21 
22 using boost::lexical_cast;
23 using ba::ip::tcp;
24 
25 // ------------------------------------------------------------------------
26 
27 
28 // ------------------------------------------------------------------------
29 
30 class tcp_connection : public ba::ip::tcp::socket, public boost::enable_shared_from_this<tcp_connection>
31 {
32 private:
33 
34  /*
35  void AsyncRead(ba::mutable_buffers_1 buffers)
36  {
37  ba::async_read(*this, buffers,
38  boost::bind(&tcp_connection::HandleReceivedData, shared_from_this(),
39  dummy::error, dummy::bytes_transferred));
40  }*/
41 
42  void AsyncWrite(const ba::const_buffers_1 &buffers)
43  {
44  ba::async_write(*this, buffers,
45  boost::bind(&tcp_connection::HandleSentData, shared_from_this(),
46  dummy::error, dummy::bytes_transferred));
47  }
48  void AsyncWait(ba::deadline_timer &timer, int seconds,
49  void (tcp_connection::*handler)(const bs::error_code&))// const
50  {
51  timer.expires_from_now(boost::posix_time::seconds(seconds));
52  timer.async_wait(boost::bind(handler, shared_from_this(), dummy::error));
53  }
54 
55  ba::deadline_timer fTriggerSendData;
56 
57  // The constructor is prvate to force the obtained pointer to be shared
58  tcp_connection(ba::io_service& ioservice) : ba::ip::tcp::socket(ioservice),
59  fTriggerSendData(ioservice)
60  {
61  }
62 
63  // Callback when writing was successfull or failed
64  void HandleSentData(const boost::system::error_code& error, size_t bytes_transferred)
65  {
66  cout << "Data sent: (transmitted=" << bytes_transferred << ") rc=" << error.message() << " (" << error << ")" << endl;
67  }
68 
69  stringstream fBuffer;
70 
71  void SendData()
72  {
73  fBuffer.str("");
74  fBuffer <<
75  "status: 00000538 \n"
76  "time_s: 764.755 \n"
77  "VOLTAGES \n"
78  " \n"
79  "enable:11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00001111 \n"
80  " done:11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00001111 \n"
81  "values:0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 \n"
82  "RESISTANCES \n"
83  " \n"
84  "enable:11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 \n"
85  " done:11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 \n"
86  "values: \n"
87  "1000.16 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
88  "3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
89  "1197.07 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
90  "558.59 677.92 817.26 989.39 1200.35 1503.06 1799.90 2204.18 \n"
91  "3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
92  "3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
93  "3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
94  "3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
95  "end.\n";
96 
97  AsyncWrite(ba::buffer(ba::const_buffer(fBuffer.str().c_str(), fBuffer.str().length())));
98  }
99 
100  void TriggerSendData(const boost::system::error_code &ec)
101  {
102  if (!is_open())
103  {
104  // For example: Here we could schedule a new accept if we
105  // would not want to allow two connections at the same time.
106  return;
107  }
108 
109  if (ec==ba::error::basic_errors::operation_aborted)
110  return;
111 
112  // Check whether the deadline has passed. We compare the deadline
113  // against the current time since a new asynchronous operation
114  // may have moved the deadline before this actor had a chance
115  // to run.
116  if (fTriggerSendData.expires_at() > ba::deadline_timer::traits_type::now())
117  return;
118 
119  // The deadline has passed.
120  SendData();
121 
122  AsyncWait(fTriggerSendData, 1, &tcp_connection::TriggerSendData);
123  }
124 
125 
126 public:
127  typedef boost::shared_ptr<tcp_connection> shared_ptr;
128 
129  static shared_ptr create(ba::io_service& io_service)
130  {
131  return shared_ptr(new tcp_connection(io_service));
132  }
133 
134  void start()
135  {
136  AsyncWait(fTriggerSendData, 1, &tcp_connection::TriggerSendData);
137  }
138 };
139 
140 
141 class tcp_server : public tcp::acceptor
142 {
143 public:
144  tcp_server(ba::io_service& ioservice, int port) :
145  tcp::acceptor(ioservice, tcp::endpoint(tcp::v4(), port))
146 
147  {
148  // We could start listening for more than one connection
149  // here, but since there is only one handler executed each time
150  // it would not make sense. Before one handle_accept is not
151  // finished no new handle_accept will be called.
152  // Workround: Start a new thread in handle_accept
153  start_accept();
154  }
155 
156 private:
158  {
159  cout << "Start accept..." << flush;
160  tcp_connection::shared_ptr new_connection = tcp_connection::create(/*acceptor_.*/get_io_service());
161 
162  // This will accept a connection without blocking
163  async_accept(*new_connection,
164  boost::bind(&tcp_server::handle_accept,
165  this,
166  new_connection,
167  ba::placeholders::error));
168 
169  cout << "start-done." << endl;
170  }
171 
172  void handle_accept(tcp_connection::shared_ptr new_connection, const boost::system::error_code& error)
173  {
174  // The connection has been accepted and is now ready to use
175 
176  // not installing a new handler will stop run()
177  cout << "Handle accept..." << flush;
178  if (!error)
179  {
180  new_connection->start();
181 
182  // The is now an open connection/server (tcp_connection)
183  // we immediatly schedule another connection
184  // This allowed two client-connection at the same time
185  start_accept();
186  }
187  cout << "handle-done." << endl;
188  }
189 };
190 
191 int main(int argc, const char **argv)
192 {
193  //try
194  {
195  ba::io_service io_service;
196 
197  int Port = argc==2 ? lexical_cast<int>(argv[1]) : 5000;
198 
199  tcp_server server(io_service, Port);
200  // ba::add_service(io_service, &server);
201  // server.add_service(...);
202  //cout << "Run..." << flush;
203 
204  // Calling run() from a single thread ensures no concurrent access
205  // of the handler which are called!!!
206  io_service.run();
207 
208  //cout << "end." << endl;
209  }
210  /*catch (std::exception& e)
211  {
212  std::cerr << e.what() << std::endl;
213  }*/
214 
215  return 0;
216 }
217 /* ====================== Buffers ===========================
218 
219 char d1[128]; ba::buffer(d1));
220 std::vector<char> d2(128); ba::buffer(d2);
221 boost::array<char, 128> d3; by::buffer(d3);
222 
223 // --------------------------------
224 char d1[128];
225 std::vector<char> d2(128);
226 boost::array<char, 128> d3;
227 
228 boost::array<mutable_buffer, 3> bufs1 = {
229  ba::buffer(d1),
230  ba::buffer(d2),
231  ba::buffer(d3) };
232 sock.read(bufs1);
233 
234 std::vector<const_buffer> bufs2;
235 bufs2.push_back(boost::asio::buffer(d1));
236 bufs2.push_back(boost::asio::buffer(d2));
237 bufs2.push_back(boost::asio::buffer(d3));
238 sock.write(bufs2);
239 
240 
241 // ======================= Read functions =========================
242 
243 ba::async_read_until --> delimiter
244 
245 streambuf buf; // Ensure validity until handler!
246 by::async_read(s, buf, ....);
247 
248 ba::async_read(s, ba:buffer(data, size), handler);
249  // Single buffer
250  boost::asio::async_read(s,
251  ba::buffer(data, size),
252  compl-func --> ba::transfer_at_least(32),
253  handler);
254 
255  // Multiple buffers
256 boost::asio::async_read(s, buffers,
257  compl-func --> boost::asio::transfer_all(),
258  handler);
259  */
260 
261 // ================= Others ===============================
262 
263  /*
264  strand Provides serialised handler execution.
265  work Class to inform the io_service when it has work to do.
266 
267 
268 io_service::
269 dispatch Request the io_service to invoke the given handler.
270 poll Run the io_service's event processing loop to execute ready
271  handlers.
272 poll_one Run the io_service's event processing loop to execute one ready
273  handler.
274 post Request the io_service to invoke the given handler and return
275  immediately.
276 reset Reset the io_service in preparation for a subsequent run()
277  invocation.
278 run Run the io_service's event processing loop.
279 run_one Run the io_service's event processing loop to execute at most
280  one handler.
281 stop Stop the io_service's event processing loop.
282 wrap Create a new handler that automatically dispatches the wrapped
283  handler on the io_service.
284 
285 strand:: The io_service::strand class provides the ability to
286  post and dispatch handlers with the guarantee that none
287  of those handlers will execute concurrently.
288 
289 dispatch Request the strand to invoke the given handler.
290 get_io_service Get the io_service associated with the strand.
291 post Request the strand to invoke the given handler and return
292  immediately.
293 wrap Create a new handler that automatically dispatches the
294  wrapped handler on the strand.
295 
296 work:: The work class is used to inform the io_service when
297  work starts and finishes. This ensures that the io_service's run() function will not exit while work is underway, and that it does exit when there is no unfinished work remaining.
298 get_io_service Get the io_service associated with the work.
299 work Constructor notifies the io_service that work is starting.
300 
301 */
302 
303 
void TriggerSendData(const boost::system::error_code &ec)
Definition: fsc.cc:100
void start_accept()
Definition: fsc.cc:157
void AsyncWait(ba::deadline_timer &timer, int seconds, void(tcp_connection::*handler)(const bs::error_code &))
Definition: fsc.cc:48
void SendData()
Definition: fsc.cc:71
tcp_connection(ba::io_service &ioservice)
Definition: fsc.cc:58
STL namespace.
void handle_accept(tcp_connection::shared_ptr new_connection, const boost::system::error_code &error)
Definition: fad.cc:578
int Port
Definition: ftm.cc:27
void HandleSentData(const boost::system::error_code &error, size_t bytes_transferred)
Definition: fsc.cc:64
boost::shared_ptr< tcp_connection > shared_ptr
Definition: fsc.cc:127
void AsyncWrite(const ba::const_buffers_1 &buffers)
Definition: fsc.cc:42
void start()
Definition: fsc.cc:134
tcp_server(ba::io_service &ioservice, int port)
Definition: fsc.cc:144
int main(int argc, const char **argv)
Definition: fsc.cc:191
static shared_ptr create(ba::io_service &io_service)
Definition: fsc.cc:129
int buffer[BUFFSIZE]
Definition: db_dim_client.c:14
stringstream fBuffer
Definition: fsc.cc:69
static void handler(int conn_id, char *packet, int size, int status)
Definition: webServer.c:635
Definition: HeadersFTM.h:14
void HandleSentData(const boost::system::error_code &, size_t)
Definition: fad.cc:107
static shared_ptr create(ba::io_service &io_service, int boardid)
Definition: fad.cc:433