diff --git a/.vscode/settings.json b/.vscode/settings.json index 11e5997..d2d6f45 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -45,6 +45,7 @@ "streambuf": "cpp", "cinttypes": "cpp", "typeinfo": "cpp", - "thread": "cpp" + "thread": "cpp", + "chrono": "cpp" } } \ No newline at end of file diff --git a/lib/tcp_socket.hpp b/lib/tcp_socket.hpp index d1819f5..1061253 100644 --- a/lib/tcp_socket.hpp +++ b/lib/tcp_socket.hpp @@ -7,9 +7,15 @@ #include #include #include +#include +#include +#include + #include #include +#define SOCKET_TIMEOUT 1000; // timeout u us + #if __linux__ #include #include @@ -25,6 +31,7 @@ #include "ip.hpp" using namespace std; +using namespace chrono; class client; // class secure; @@ -52,7 +59,7 @@ class server { ~server (); void sync(void (*handlecli)(client&), const uint timeout = 100); - void async(const uint limit, void (*handlecli)(client&, mutex&), const uint timeout = 100); + void async(const uint limit, void (*handlecli)(client&), const uint timeout = 100); }; @@ -87,6 +94,7 @@ class client { #endif struct sockaddr_in addr; SSL* ssl = NULL; + uint _timeout = 100; // timeout u ms // server s klijentima const server* srv; // klijent sa serverom @@ -102,4 +110,27 @@ class client { string pull (size_t byte_limit = 1024); }; + +class ConnectionException : public exception { +public: + ConnectionException(const string& message, const string& data, const bool& interrupted = false): message_(message), data_(data), interrupted_(interrupted) {} + + virtual const char* what() const noexcept { + return message_.c_str(); + } + + const string& getData() const { + return data_; + } + + const bool& isInterrupted() const { + return interrupted_; + } + +private: + string message_; + string data_; + bool interrupted_; +}; + #endif \ No newline at end of file diff --git a/src/tcp_socket.cpp b/src/tcp_socket.cpp index f1fe0c6..11eebc8 100644 --- a/src/tcp_socket.cpp +++ b/src/tcp_socket.cpp @@ -64,22 +64,26 @@ void server::sync(void (*handlecli)(client&), const uint timeout) { * Nije moguće proslijediti druge parametre; */ -void server::async(const uint limit, void (*handlecli)(client&, mutex&), const uint timeout) { - mutex io; - do { - for (uint i=0; i~client(); + cli = new client(this, timeout, securefds); + } + } + } + })); + } - } while (true); + for (uint i=0; isock, (struct sockaddr *)&(srv->addr), (socklen_t*)&len)) < 0) { throw string("[ERROR] Unable to accept client connection "); @@ -244,8 +250,8 @@ client::client(const server *_srv, const uint timeout, SSL_CTX* securefds) { #if __linux__ struct timeval tv; - tv.tv_sec = timeout/1000; - tv.tv_usec = (timeout%1000)*1000; + tv.tv_sec = 0; + tv.tv_usec = SOCKET_TIMEOUT; if (setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval))) { throw string("[ERROR] Unable to set timeout "); @@ -258,9 +264,6 @@ client::client(const server *_srv, const uint timeout, SSL_CTX* securefds) { } #endif - - - if (securefds) { ssl = SSL_new(securefds); if (!ssl) { @@ -338,8 +341,7 @@ bool client::push(const string msg) { } if (sent == -1) { - // Greška pri slanju poruke - return false; + throw string("[ERRNO] (push) - Error code: " + to_string(errno) + " Detail: " + strerror(errno)); } total_sent += sent; @@ -352,11 +354,31 @@ bool client::push(const string msg) { * Metoda klase client za primanje poruke preko soketa * Prima dozvoljeni broj karaktera koji će primiti * Vraća string primljene poruke + * + * Funkcija baca izuzetke koji se moraju uhvatiti za pravilno rukovođenje vezom + * Potrebno je i baciti dalje taj izuzetak ukoliko se koriste server async metode + * PRILOG + * ---------------------------------------------------------------- + * try { + fromclient = cli.pull(); + } + catch(const ConnectionException except) { + if (except.isInterrupted()) { + throw except; + } + else { + cout << "[EXCEPT] " << except.what() << endl; + fromclient = except.getData(); + } + } + * ----------------------------------------------------------------- + * */ string client::pull(size_t byte_limit) { char res[byte_limit] = {0}; size_t total_received = 0; + auto start = high_resolution_clock::now(); while (total_received < byte_limit) { ssize_t received = 0; @@ -367,15 +389,21 @@ string client::pull(size_t byte_limit) { received = recv(conn, res + total_received, byte_limit - total_received, 0); } + cout << "Primljeno " << received << endl; + if (received == -1) { - // Greška pri primanju poruke - break; + throw ConnectionException(strerror(errno), string(res, total_received)); } else if (received == 0) { - // Veza je prekinuta - break; + throw ConnectionException("The socket is broken", string(res), true); } total_received += received; + + auto cycle = high_resolution_clock::now(); + if (duration_cast(cycle - start).count() > _timeout) { + cout << "TIMEOUT" << endl; + throw ConnectionException("Timeout", string(res)); + } } return string(res); diff --git a/test/client.cpp b/test/client.cpp index f4a51e3..99cfc0a 100644 --- a/test/client.cpp +++ b/test/client.cpp @@ -1,29 +1,31 @@ #include #include +#include #include "../lib/tcp_socket.hpp" using namespace std; +using namespace chrono; int main() { try { - uint n = 10000; + // uint n = 10000; - vector thr; - for (uint i=0; i thr; + // for (uint i=0; i(t2 - t1).count() << endl; + + + + while (true) { + + + + + auto t3 = high_resolution_clock::now(); + mycli.push("Helooo"); + auto t4 = high_resolution_clock::now(); + cout << "Send : " << duration_cast(t4 - t3).count() << endl; + auto t5 = high_resolution_clock::now(); + string msg; + try { + msg = mycli.pull(); + } catch (const ConnectionException err) { + cout << err.what() << endl; + msg = err.getData(); + } + cout << msg << endl; + auto t6 = high_resolution_clock::now(); + cout << "Recive : " << duration_cast(t6 - t5).count() << endl; + // break; + } + } + catch (const string err) { cout << err << endl; } diff --git a/test/client.o b/test/client.o index 8a01c9f..4789f27 100755 Binary files a/test/client.o and b/test/client.o differ diff --git a/test/server.cpp b/test/server.cpp index edfe269..12944d4 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -1,8 +1,12 @@ #include +#include + #include "../lib/tcp_socket.hpp" using namespace std; +using namespace chrono; + int main() { try{ @@ -52,15 +56,31 @@ int main() { cout << "init server " << endl; server myserver(5000, 100); cout << "init client " << endl; - myserver.async(8, [](client &cli, mutex &io) { - cout << "Klijent " << cli.ipv4 << endl; - string fromclient = cli.pull(); - io.lock(); - cout << "S klijenta " << fromclient << endl; - io.unlock(); - // fromclient += teststr; + myserver.async(8, [](client &cli) { + auto t3 = high_resolution_clock::now(); + string fromclient; + try { + fromclient = cli.pull(); + } + catch(const ConnectionException except) { + if (except.isInterrupted()) { + throw except; + } + else { + cout << "[EXCEPT] " << except.what() << endl; + fromclient = except.getData(); + } + } + auto t4 = high_resolution_clock::now(); + cout << "Recive : " << duration_cast(t4 - t3).count() << endl; + + cout << "> " << fromclient << endl; + auto t5 = high_resolution_clock::now(); cli.push(fromclient); - }, 200); + auto t6 = high_resolution_clock::now(); + cout << "Response : " << duration_cast(t6 - t5).count() << endl; + + }); // string teststr = " Idemooo"; diff --git a/test/server.o b/test/server.o index 73fac41..975d12e 100755 Binary files a/test/server.o and b/test/server.o differ