Mercurial > code
changeset 509:36e81ef34ed5
Sockets: update examples
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 23 Feb 2016 12:56:41 +0100 |
parents | 8fc7fe1ec915 |
children | f1749ac790d0 |
files | modules/sockets/examples/ElapsedTimer.cpp modules/sockets/examples/ElapsedTimer.h modules/sockets/examples/blocking-accept.cpp modules/sockets/examples/blocking-connect.cpp modules/sockets/examples/elapsed-timer.cpp modules/sockets/examples/elapsed-timer.h modules/sockets/examples/non-blocking-accept.cpp modules/sockets/examples/non-blocking-connect.cpp modules/sockets/examples/stream-client.cpp modules/sockets/examples/stream-server.cpp modules/sockets/sockets.h |
diffstat | 11 files changed, 190 insertions(+), 299 deletions(-) [+] |
line wrap: on
line diff
--- a/modules/sockets/examples/ElapsedTimer.cpp Tue Feb 23 12:04:40 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * ElapsedTimer.cpp -- measure elapsed time - * - * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ElapsedTimer.h" - -using std::chrono::duration_cast; -using std::chrono::high_resolution_clock; -using std::chrono::milliseconds; - -ElapsedTimer::ElapsedTimer() noexcept -{ - m_last = high_resolution_clock::now(); -} - -void ElapsedTimer::pause() noexcept -{ - /* - * When we put the timer on pause, do not forget to set the already - * elapsed time. - */ - (void)elapsed(); - m_paused = true; -} - -void ElapsedTimer::restart() noexcept -{ - m_paused = false; - m_last = high_resolution_clock::now(); -} - -void ElapsedTimer::reset() noexcept -{ - m_elapsed = 0; - m_last = high_resolution_clock::now(); -} - -unsigned ElapsedTimer::elapsed() noexcept -{ - if (!m_paused) { - m_elapsed += duration_cast<milliseconds>(high_resolution_clock::now() - m_last).count(); - m_last = high_resolution_clock::now(); - } - - return m_elapsed; -} \ No newline at end of file
--- a/modules/sockets/examples/ElapsedTimer.h Tue Feb 23 12:04:40 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * ElapsedTimer.h -- measure elapsed time - * - * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _ELAPSED_TIMER_H_ -#define _ELAPSED_TIMER_H_ - -/** - * @file ElapsedTimer.h - * @brief Measure elapsed time - */ - -#include <chrono> - -/** - * @class ElapsedTimer - * @brief Measure elapsed time - * - * This class provides an abstraction to measure elapsed time since the - * construction of the object. - * - * It uses std::chrono::high_resolution_clock for more precision and uses - * milliseconds only. - */ -class ElapsedTimer { -public: - using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>; - -private: - TimePoint m_last; - bool m_paused{false}; - unsigned m_elapsed{0}; - -public: - /** - * Construct the elapsed timer, start counting. - */ - ElapsedTimer() noexcept; - - /** - * Put the timer on pause, the already elapsed time is stored. - */ - void pause() noexcept; - - /** - * Restart the timer, does not reset it. - */ - void restart() noexcept; - - /** - * Reset the timer to 0. - */ - void reset() noexcept; - - /** - * Get the number of elapsed milliseconds. - * - * @return the milliseconds - */ - unsigned elapsed() noexcept; -}; - -#endif // !_ELAPSED_TIMER_H_
--- a/modules/sockets/examples/blocking-accept.cpp Tue Feb 23 12:04:40 2016 +0100 +++ b/modules/sockets/examples/blocking-accept.cpp Tue Feb 23 12:56:41 2016 +0100 @@ -9,7 +9,7 @@ #include <iostream> -#include "Sockets.h" +#include "sockets.h" #if !defined(WITH_PORT) # define WITH_PORT 16000 @@ -39,7 +39,7 @@ listener.set(master.handle(), net::Condition::Readable); listener.wait(std::chrono::seconds(WITH_TIMEOUT)); - client = master.accept(nullptr); + master.accept(client); } catch (const net::Error &error) { std::cerr << "error: " << error.what() << std::endl; std::exit(1);
--- a/modules/sockets/examples/blocking-connect.cpp Tue Feb 23 12:04:40 2016 +0100 +++ b/modules/sockets/examples/blocking-connect.cpp Tue Feb 23 12:56:41 2016 +0100 @@ -22,28 +22,26 @@ # define WITH_TIMEOUT 30 #endif -#include "ElapsedTimer.h" -#include "Sockets.h" +#include "elapsed-timer.h" +#include "sockets.h" int main() { #if defined(WITH_SSL) - net::SocketTls<net::address::Ip> socket; + net::SocketTls<net::address::Ipv4> socket; #else - net::SocketTcp<net::address::Ip> socket; + net::SocketTcp<net::address::Ipv4> socket; #endif try { std::cout << "Trying to connect to " << WITH_HOST << ":" << WITH_PORT << std::endl; - socket.connect(net::address::Ip{WITH_HOST, WITH_PORT}); + socket.connect(net::address::Ip(WITH_HOST, WITH_PORT)); } catch (const net::Error &error) { std::cerr << "error: " << error.what() << std::endl; std::exit(1); } - if (socket.state() == net::State::Connected) { - std::cout << "Successfully connected!" << std::endl; - } + std::cout << "Successfully connected!" << std::endl; return 0; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/elapsed-timer.cpp Tue Feb 23 12:56:41 2016 +0100 @@ -0,0 +1,60 @@ +/* + * elapsed-timer.cpp -- measure elapsed time + * + * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "elapsed-timer.h" + +using std::chrono::duration_cast; +using std::chrono::high_resolution_clock; +using std::chrono::milliseconds; + +ElapsedTimer::ElapsedTimer() noexcept +{ + m_last = high_resolution_clock::now(); +} + +void ElapsedTimer::pause() noexcept +{ + /* + * When we put the timer on pause, do not forget to set the already + * elapsed time. + */ + (void)elapsed(); + m_paused = true; +} + +void ElapsedTimer::restart() noexcept +{ + m_paused = false; + m_last = high_resolution_clock::now(); +} + +void ElapsedTimer::reset() noexcept +{ + m_elapsed = 0; + m_last = high_resolution_clock::now(); +} + +unsigned ElapsedTimer::elapsed() noexcept +{ + if (!m_paused) { + m_elapsed += duration_cast<milliseconds>(high_resolution_clock::now() - m_last).count(); + m_last = high_resolution_clock::now(); + } + + return m_elapsed; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/sockets/examples/elapsed-timer.h Tue Feb 23 12:56:41 2016 +0100 @@ -0,0 +1,77 @@ +/* + * elapsed-timer.h -- measure elapsed time + * + * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _ELAPSED_TIMER_H_ +#define _ELAPSED_TIMER_H_ + +/** + * @file ElapsedTimer.h + * @brief Measure elapsed time + */ + +#include <chrono> + +/** + * @class ElapsedTimer + * @brief Measure elapsed time + * + * This class provides an abstraction to measure elapsed time since the + * construction of the object. + * + * It uses std::chrono::high_resolution_clock for more precision and uses + * milliseconds only. + */ +class ElapsedTimer { +public: + using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>; + +private: + TimePoint m_last; + bool m_paused{false}; + unsigned m_elapsed{0}; + +public: + /** + * Construct the elapsed timer, start counting. + */ + ElapsedTimer() noexcept; + + /** + * Put the timer on pause, the already elapsed time is stored. + */ + void pause() noexcept; + + /** + * Restart the timer, does not reset it. + */ + void restart() noexcept; + + /** + * Reset the timer to 0. + */ + void reset() noexcept; + + /** + * Get the number of elapsed milliseconds. + * + * @return the milliseconds + */ + unsigned elapsed() noexcept; +}; + +#endif // !_ELAPSED_TIMER_H_
--- a/modules/sockets/examples/non-blocking-accept.cpp Tue Feb 23 12:04:40 2016 +0100 +++ b/modules/sockets/examples/non-blocking-accept.cpp Tue Feb 23 12:56:41 2016 +0100 @@ -3,21 +3,21 @@ * * Options: * - WITH_PORT (int), the port to use (default: 16000) - * - WITH_TIMEOUT (int), number of seconds before giving up (default: 60) + * - WITH_TIMEOUT (int), number of milliseconds before giving up (default: 3000) * - WITH_SSL (bool), true to test with SSL (default: false) */ #include <iostream> -#include "ElapsedTimer.h" -#include "Sockets.h" +#include "elapsed-timer.h" +#include "sockets.h" #if !defined(WITH_PORT) # define WITH_PORT 16000 #endif #if !defined(WITH_TIMEOUT) -# define WITH_TIMEOUT 60 +# define WITH_TIMEOUT 3000 #endif int main() @@ -31,6 +31,8 @@ #endif net::Listener<> listener; + net::Condition cond; + ElapsedTimer timer; // 1. Create the master socket for listening. @@ -39,26 +41,40 @@ master.set(net::option::SockBlockMode{false}); master.bind(net::address::Ip{"*", WITH_PORT}); master.listen(); + + listener.set(master.handle(), net::Condition::Readable); } catch (const net::Error &error) { std::cerr << "error: " << error.what() << std::endl; std::exit(1); } - while (client.state() != net::State::Accepted && timer.elapsed() < (WITH_TIMEOUT * 1000)) { + while (!client.isOpen() && timer.elapsed() < WITH_TIMEOUT) { try { - if (client.state() == net::State::Closed) { + if (!client.isOpen()) { // 2. Wait for a pre-accept process. - listener.set(master.handle(), net::Condition::Readable); listener.wait(std::chrono::seconds(WITH_TIMEOUT)); - client = master.accept(nullptr); - client.set(net::option::SockBlockMode{false}); + master.accept(client, nullptr, &cond); + client.set(net::option::SockBlockMode(false)); listener.remove(master.handle()); + + std::cout << "Accepting new client" << std::endl; + + if (cond != net::Condition::None) { + std::cout << "Client accept state not complete" << std::endl; + listener.set(client.handle(), cond); + } } else { // 3. Wait for the accept process to complete. + std::cout << "Continuing accept for the client" << std::endl; + + listener.wait(std::chrono::seconds(WITH_TIMEOUT - timer.elapsed())); + client.accept(&cond); listener.remove(client.handle()); - listener.set(client.handle(), client.condition()); - listener.wait(std::chrono::seconds(WITH_TIMEOUT)); - client.accept(); + + if (cond != net::Condition::None) { + std::cout << "Client accept state not complete" << std::endl; + listener.set(client.handle(), cond); + } } } catch (const net::Error &error) { std::cerr << error.function() << ": " << error.what() << std::endl; @@ -66,7 +82,8 @@ } } - std::cout << "Client successfully accepted!" << std::endl; + if (client.isOpen()) + std::cout << "Client successfully accepted!" << std::endl; - return 0; + return 0; }
--- a/modules/sockets/examples/non-blocking-connect.cpp Tue Feb 23 12:04:40 2016 +0100 +++ b/modules/sockets/examples/non-blocking-connect.cpp Tue Feb 23 12:56:41 2016 +0100 @@ -4,7 +4,7 @@ * Options: * - WITH_HOST (string literal), the host to try (default: "malikania.fr") * - WITH_PORT (int), the port to use (default: 80) - * - WITH_TIMEOUT (int), number of seconds before giving up (default: 30) + * - WITH_TIMEOUT (int), number of milliseconds before giving up (default: 3000) * - WITH_SSL (bool), true to test with SSL (default: false) */ @@ -19,11 +19,11 @@ #endif #if !defined(WITH_TIMEOUT) -# define WITH_TIMEOUT 30 +# define WITH_TIMEOUT 3000 #endif -#include "ElapsedTimer.h" -#include "Sockets.h" +#include "elapsed-timer.h" +#include "sockets.h" int main() { @@ -34,33 +34,32 @@ #endif net::Listener<> listener; + net::Condition cond; ElapsedTimer timer; // 1. Set to non-blocking. - socket.set(net::option::SockBlockMode{false}); + socket.set(net::option::SockBlockMode(false)); try { std::cout << "Trying to connect to " << WITH_HOST << ":" << WITH_PORT << std::endl; // 2. Initial connection process. - socket.connect(net::address::Ip{WITH_HOST, WITH_PORT}); + socket.connect(net::address::Ip(WITH_HOST, WITH_PORT), &cond); - while (socket.state() != net::State::Connected) { + while (cond != net::Condition::None && timer.elapsed() < WITH_TIMEOUT) { listener.remove(socket.handle()); // 2. Now complete by waiting for the appropriate condition. - listener.set(socket.handle(), socket.condition()); - listener.wait(std::chrono::seconds(WITH_TIMEOUT)); - socket.connect(); + listener.set(socket.handle(), cond); + listener.wait(std::chrono::milliseconds(WITH_TIMEOUT - timer.elapsed())); + socket.connect(&cond); } } catch (const net::Error &error) { std::cerr << "error: " << error.what() << std::endl; std::exit(1); } - if (socket.state() == net::State::Connected) { - std::cout << "Successfully connected!" << std::endl; - } + std::cout << "Successfully connected!" << std::endl; return 0; }
--- a/modules/sockets/examples/stream-client.cpp Tue Feb 23 12:04:40 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * stream-server -- example of stream server - * - * Options: - * - WITH_PORT (int) which port to use (default: 12000) - * - WITH_HOST (string literal) which host to connect (default: "localhost") - * - WITH_SSL (bool) true to use SSL (default: false) - */ - -#include <iostream> - -#include "Sockets.h" - -#if !defined(WITH_PORT) -# define WITH_PORT 12000 -#endif - -#if !defined(WITH_HOST) -# define WITH_HOST "localhost" -#endif - -#if defined(WITH_SSL) -using Client = net::StreamClient<net::address::Ip, net::protocol::Tls>; -#else -using Client = net::StreamClient<net::address::Ip, net::protocol::Tcp>; -#endif - -int main() -{ - Client client; - - /* - * Unfortunately at the moment the socket state is not changed, this will be done - * in the future. - */ - bool connected{true}; - - client.setConnectionHandler([&] () { - std::cout << "client: successfully connected" << std::endl; - client.send("Hello world!"); - }); - client.setDisconnectionHandler([&] () { - std::cout << "client: disconnected" << std::endl; - connected = false; - }); - client.setErrorHandler([&] (const net::Error &error) { - std::cout << "client: error: " << error.function() << ": " << error.what() << std::endl; - connected = false; - }); - client.setReadHandler([] (const std::string &data) { - std::cout << "client: received: " << data << std::endl; - }); - client.setWriteHandler([] (const std::string &data) { - std::cout << "client: sent: " << data << std::endl; - }); - - client.connect(net::address::Ip{WITH_HOST, WITH_PORT}); - - while (connected) { - client.poll(); - } - - std::cout << "client: exiting" << std::endl; - - return 0; -}
--- a/modules/sockets/examples/stream-server.cpp Tue Feb 23 12:04:40 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * stream-server -- example of stream server - * - * Options: - * - WITH_PORT (int) which port to use (default: 12000) - * - WITH_SSL (bool) true to use SSL (default: false) - */ - -#include <iostream> - -#include "Sockets.h" - -#if !defined(WITH_PORT) -# define WITH_PORT 12000 -#endif - -#if defined(WITH_SSL) -using Server = net::StreamServer<net::address::Ip, net::protocol::Tls>; -using Connection = net::StreamConnection<net::address::Ip, net::protocol::Tls>; -#else -using Server = net::StreamServer<net::address::Ip, net::protocol::Tcp>; -using Connection = net::StreamConnection<net::address::Ip, net::protocol::Tcp>; -#endif - -int main() -{ -#if defined(WITH_SSL) - net::protocol::Tls protocol; - - protocol.setVerify(false); - protocol.setPrivateKey("test.key"); - protocol.setCertificate("test.crt"); - protocol.setMethod(net::ssl::Tlsv1); - - Server server{std::move(protocol), net::address::Ip{"*", WITH_PORT}}; -#else - Server server{net::protocol::Tcp{}, net::address::Ip{"*", WITH_PORT}}; -#endif - - server.setConnectionHandler([] (const std::shared_ptr<Connection> &client) { - std::cout << "server: new client connected" << std::endl; - client->send("Welcome to our server dude"); - }); - server.setReadHandler([] (const std::shared_ptr<Connection> &, const std::string &buffer) { - std::cout << "server: received: " << buffer << std::endl; - }); - server.setWriteHandler([] (const std::shared_ptr<Connection> &, const std::string &buffer) { - std::cout << "server: sent: " << buffer << std::endl; - }); - server.setDisconnectionHandler([] (const std::shared_ptr<Connection> &) { - std::cout << "server: client disconnected" << std::endl; - }); - - while (true) { - server.poll(-1); - } - - return 0; -}