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

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