source: trunk/FACT++/src/fsc.cc@ 14797

Last change on this file since 14797 was 14615, checked in by tbretz, 12 years ago
Removed obsolete includes.
File size: 10.2 KB
Line 
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
9using boost::lexical_cast;
10
11#include "Time.h"
12
13#include "HeadersFTM.h"
14
15using namespace std;
16using namespace FTM;
17
18namespace ba = boost::asio;
19namespace bs = boost::system;
20namespace dummy = ba::placeholders;
21
22using boost::lexical_cast;
23using ba::ip::tcp;
24
25// ------------------------------------------------------------------------
26
27
28// ------------------------------------------------------------------------
29
30class tcp_connection : public ba::ip::tcp::socket, public boost::enable_shared_from_this<tcp_connection>
31{
32private:
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
126public:
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
141class tcp_server : public tcp::acceptor
142{
143public:
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
156private:
157 void start_accept()
158 {
159 cout << "Start accept..." << flush;
160 tcp_connection::shared_ptr new_connection = tcp_connection::create(/*acceptor_.*/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
191int 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
219char d1[128]; ba::buffer(d1));
220std::vector<char> d2(128); ba::buffer(d2);
221boost::array<char, 128> d3; by::buffer(d3);
222
223// --------------------------------
224char d1[128];
225std::vector<char> d2(128);
226boost::array<char, 128> d3;
227
228boost::array<mutable_buffer, 3> bufs1 = {
229 ba::buffer(d1),
230 ba::buffer(d2),
231 ba::buffer(d3) };
232sock.read(bufs1);
233
234std::vector<const_buffer> bufs2;
235bufs2.push_back(boost::asio::buffer(d1));
236bufs2.push_back(boost::asio::buffer(d2));
237bufs2.push_back(boost::asio::buffer(d3));
238sock.write(bufs2);
239
240
241// ======================= Read functions =========================
242
243ba::async_read_until --> delimiter
244
245streambuf buf; // Ensure validity until handler!
246by::async_read(s, buf, ....);
247
248ba::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
256boost::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
268io_service::
269dispatch Request the io_service to invoke the given handler.
270poll Run the io_service's event processing loop to execute ready
271 handlers.
272poll_one Run the io_service's event processing loop to execute one ready
273 handler.
274post Request the io_service to invoke the given handler and return
275 immediately.
276reset Reset the io_service in preparation for a subsequent run()
277 invocation.
278run Run the io_service's event processing loop.
279run_one Run the io_service's event processing loop to execute at most
280 one handler.
281stop Stop the io_service's event processing loop.
282wrap Create a new handler that automatically dispatches the wrapped
283 handler on the io_service.
284
285strand:: 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
289dispatch Request the strand to invoke the given handler.
290get_io_service Get the io_service associated with the strand.
291post Request the strand to invoke the given handler and return
292 immediately.
293wrap Create a new handler that automatically dispatches the
294 wrapped handler on the strand.
295
296work:: 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.
298get_io_service Get the io_service associated with the work.
299work Constructor notifies the io_service that work is starting.
300
301*/
302
303
Note: See TracBrowser for help on using the repository browser.