Working on socket pool..
This commit is contained in:
parent
c030b22446
commit
5fa791cf5e
12
.vscode/settings.json
vendored
12
.vscode/settings.json
vendored
@ -45,6 +45,16 @@
|
|||||||
"streambuf": "cpp",
|
"streambuf": "cpp",
|
||||||
"cinttypes": "cpp",
|
"cinttypes": "cpp",
|
||||||
"typeinfo": "cpp",
|
"typeinfo": "cpp",
|
||||||
"thread": "cpp"
|
"thread": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"semaphore": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stop_token": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -53,7 +53,9 @@ class server {
|
|||||||
|
|
||||||
void sync(void (*handlecli)(client&), const uint timeout = 100);
|
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&, mutex&), const uint timeout = 100);
|
||||||
void pool(const uint limit, void (*handlecli)(client&, mutex&), const uint timeout = 100);
|
// void syncPool(void (*handlecli)(client&), const uint timeout = 100);
|
||||||
|
void asyncPool(const uint limit, void (*handlecli)(client&), const uint timeout = 100);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -88,8 +90,12 @@ class client {
|
|||||||
#endif
|
#endif
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
SSL* ssl = NULL;
|
SSL* ssl = NULL;
|
||||||
|
string _address;
|
||||||
|
ushort _port;
|
||||||
|
uint _timeout;
|
||||||
|
SSL_CTX* _securefds = NULL;
|
||||||
// server s klijentima
|
// server s klijentima
|
||||||
const server* srv;
|
const server* srv = NULL;
|
||||||
// klijent sa serverom
|
// klijent sa serverom
|
||||||
string ipv4;
|
string ipv4;
|
||||||
string ipv6;
|
string ipv6;
|
||||||
@ -101,6 +107,7 @@ class client {
|
|||||||
~client ();
|
~client ();
|
||||||
bool push (const string msg);
|
bool push (const string msg);
|
||||||
string pull (size_t byte_limit = 1024);
|
string pull (size_t byte_limit = 1024);
|
||||||
|
bool reconnect();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ustvari ne znam jel konekcija aktivna
|
* ustvari ne znam jel konekcija aktivna
|
||||||
@ -109,18 +116,20 @@ class client {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Pool {
|
class clientPool {
|
||||||
public:
|
public:
|
||||||
|
mutex io;
|
||||||
uint numcli;
|
uint numcli;
|
||||||
vector<pair<mutex*, client*>> drops;
|
vector<pair<mutex*, client*>> drops;
|
||||||
|
|
||||||
// konstruktor za klijente bez servera
|
// konstruktor za klijente bez servera
|
||||||
Pool (const uint _numcli, const string address, const ushort port, const uint timeout = 100, SSL_CTX* securefds = NULL);
|
clientPool (const uint _numcli, const string address, const ushort port, const uint timeout = 100, SSL_CTX* securefds = NULL);
|
||||||
// konstruktor za klijente sa serverom
|
// konstruktor za klijente sa serverom
|
||||||
Pool (const server *_srv, const uint _numcli, const uint timeout = 100, SSL_CTX* securefds = NULL);
|
clientPool (const server *_srv, const uint _numcli, const uint timeout = 100, SSL_CTX* securefds = NULL);
|
||||||
~Pool();
|
~clientPool();
|
||||||
|
|
||||||
void run();
|
pair<mutex*, client*>* pickup();
|
||||||
|
void release(pair<mutex*, client*>* drop);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,6 +83,53 @@ void server::async(const uint limit, void (*handlecli)(client&, mutex&), const u
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metoda za sinkroni rad s klijentima, prima pokazivač na funkciju i timeout;
|
||||||
|
* Funkcija handlecli prima referencu tipa client - važno za definiranje funkcija koje se šalju;
|
||||||
|
* Nije moguće proslijediti druge parametre;
|
||||||
|
*/
|
||||||
|
|
||||||
|
// void server::syncPool(void (*handlecli)(client&), const uint timeout) {
|
||||||
|
// do {
|
||||||
|
// client cli(this, timeout, securefds);
|
||||||
|
// handlecli(cli);
|
||||||
|
// } while (true);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metoda za asinkdorni rad s klijentima, prima limit, pokazivač na funkciju i timeout;
|
||||||
|
* Funkcija handlecli prima referencu tipa client - važno za definiranje funkcija koje se šalju;
|
||||||
|
* Nije moguće proslijediti druge parametre;
|
||||||
|
*/
|
||||||
|
|
||||||
|
void server::asyncPool(const uint limit, void (*handlecli)(client&), const uint timeout) {
|
||||||
|
clientPool clipool(this, limit, timeout, securefds);
|
||||||
|
|
||||||
|
for (uint i=0; i<limit; i++) {
|
||||||
|
thr.push_back(thread( [&]() {
|
||||||
|
while (true) {
|
||||||
|
pair<mutex*, client*>* cli = clipool.pickup();
|
||||||
|
handlecli(*(cli->second));
|
||||||
|
clipool.release(cli);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i=0; i<limit; i++) {
|
||||||
|
thr[i].join();
|
||||||
|
}
|
||||||
|
thr.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destruktor varijable tipa server
|
* Destruktor varijable tipa server
|
||||||
*/
|
*/
|
||||||
@ -369,9 +416,13 @@ string client::pull(size_t byte_limit) {
|
|||||||
|
|
||||||
if (received == -1) {
|
if (received == -1) {
|
||||||
// Greška pri primanju poruke
|
// Greška pri primanju poruke
|
||||||
|
cout << "Da vidim jel ovdje kad nije poslo " << endl;
|
||||||
break;
|
break;
|
||||||
} else if (received == 0) {
|
} else if (received == 0) {
|
||||||
// Veza je prekinuta
|
// Veza je prekinuta - treba pozvati destruktor
|
||||||
|
cout << "Destruktor " << endl;
|
||||||
|
// this->~client();
|
||||||
|
throw string("[WARNING] Socket closed remotely");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,8 +432,111 @@ string client::pull(size_t byte_limit) {
|
|||||||
return string(res);
|
return string(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool client::reconnect() {
|
||||||
|
if (_address.empty() && srv != NULL) {
|
||||||
|
// srv = _srv;
|
||||||
|
socklen_t len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
Pool::Pool(const uint _numcli, const string address, const ushort port, const uint timeout, SSL_CTX* securefds) {
|
if ((conn = accept(srv->sock, (struct sockaddr *)&(srv->addr), (socklen_t*)&len)) < 0) {
|
||||||
|
throw string("[ERROR] Unable to accept client connection ");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __linux__
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = _timeout/1000;
|
||||||
|
tv.tv_usec = (_timeout%1000)*1000;
|
||||||
|
|
||||||
|
if (setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval))) {
|
||||||
|
throw string("[ERROR] Unable to set timeout ");
|
||||||
|
}
|
||||||
|
#elif _WIN32
|
||||||
|
DWORD tv = timeout;
|
||||||
|
|
||||||
|
if (setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv))) {
|
||||||
|
throw string("[ERROR] Unable to set timeout ");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (_securefds) {
|
||||||
|
ssl = SSL_new(_securefds);
|
||||||
|
if (!ssl) {
|
||||||
|
throw string("[ERROR] Creating SSL object ");
|
||||||
|
}
|
||||||
|
SSL_set_fd(ssl, conn);
|
||||||
|
|
||||||
|
// Perform SSL handshake
|
||||||
|
if (SSL_accept(ssl) <= 0) {
|
||||||
|
SSL_free(ssl);
|
||||||
|
throw string("[ERROR] Performing SSL handshake ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char ipv4_buff[INET_ADDRSTRLEN];
|
||||||
|
char ipv6_buff[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &(srv->addr.sin_addr), ipv4_buff, INET_ADDRSTRLEN);
|
||||||
|
ipv4 = ipv4_buff;
|
||||||
|
inet_ntop(AF_INET6, &(srv->addr.sin_addr), ipv6_buff, INET6_ADDRSTRLEN);
|
||||||
|
ipv6 = ipv6_buff;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) {
|
||||||
|
throw string("[ERROR] Unable to set WinSock " + to_string(WSAGetLastError()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
conn = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (conn < 0) {
|
||||||
|
throw string("[ERROR] Unable to open TCP socket ");
|
||||||
|
}
|
||||||
|
|
||||||
|
const string _address = isIPAddress(_address) ? _address : ipFromDomain(_address);
|
||||||
|
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_addr.s_addr = inet_addr(_address.c_str());
|
||||||
|
addr.sin_port = htons(_port);
|
||||||
|
|
||||||
|
if (connect(conn, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) != 0) {
|
||||||
|
throw string("Unable to connect to server ");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __linux__
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = _timeout/1000;
|
||||||
|
tv.tv_usec = (_timeout%1000)*1000;
|
||||||
|
|
||||||
|
if (setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval))) {
|
||||||
|
throw string("[ERROR] Unable to set timeout ");
|
||||||
|
}
|
||||||
|
#elif _WIN32
|
||||||
|
DWORD tv = timeout;
|
||||||
|
if (setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv))) {
|
||||||
|
throw string("[ERROR] Unable to set timeout ");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (_securefds) {
|
||||||
|
ssl = SSL_new(_securefds);
|
||||||
|
if (!ssl) {
|
||||||
|
throw string("[ERROR] Creating SSL object ");
|
||||||
|
}
|
||||||
|
SSL_set_fd(ssl, conn);
|
||||||
|
|
||||||
|
// Perform the SSL handshake
|
||||||
|
if (SSL_connect(ssl) <= 0) {
|
||||||
|
SSL_free(ssl);
|
||||||
|
throw string("[ERROR] Performing SSL handshake ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clientPool::clientPool(const uint _numcli, const string address, const ushort port, const uint timeout, SSL_CTX* securefds) {
|
||||||
if (_numcli > 1 ) {
|
if (_numcli > 1 ) {
|
||||||
numcli = _numcli;
|
numcli = _numcli;
|
||||||
}
|
}
|
||||||
@ -397,7 +551,7 @@ Pool::Pool(const uint _numcli, const string address, const ushort port, const ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Pool::Pool(const server *_srv, const uint _numcli, const uint timeout = 100, SSL_CTX* securefds = NULL) {
|
clientPool::clientPool(const server *_srv, const uint _numcli, const uint timeout, SSL_CTX* securefds) {
|
||||||
if (_numcli > 1 ) {
|
if (_numcli > 1 ) {
|
||||||
numcli = _numcli;
|
numcli = _numcli;
|
||||||
}
|
}
|
||||||
@ -406,12 +560,33 @@ Pool::Pool(const server *_srv, const uint _numcli, const uint timeout = 100, SSL
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (uint i=0; i<numcli; i++) {
|
for (uint i=0; i<numcli; i++) {
|
||||||
|
cout << "init clients " << i << endl;
|
||||||
drops.push_back(make_pair(new mutex, new client(_srv, timeout, securefds)));
|
drops.push_back(make_pair(new mutex, new client(_srv, timeout, securefds)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Pool::~Pool() {
|
pair<mutex*, client*>* clientPool::pickup() {
|
||||||
|
cout << "Uzimam clienta " << endl;
|
||||||
|
lock_guard<mutex> master(io);
|
||||||
|
while (true) {
|
||||||
|
for (uint i=0; i<drops.size(); i++) {
|
||||||
|
cout << "Pokušavam s " << i << endl;
|
||||||
|
|
||||||
|
if (drops[i].first->try_lock()) {
|
||||||
|
cout << "Odabrao sam " << i << endl;
|
||||||
|
|
||||||
|
return &drops[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clientPool::release(pair<mutex*, client*>* drop) {
|
||||||
|
drop->first->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
clientPool::~clientPool() {
|
||||||
|
|
||||||
numcli = 0;
|
numcli = 0;
|
||||||
drops.clear();
|
drops.clear();
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#include "../lib/tcp_socket.hpp"
|
#include "../lib/tcp_socket.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace chrono;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|
||||||
@ -26,12 +28,20 @@ int main() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
uint i = 0;
|
uint i = 0;
|
||||||
client mycli("localhost", 5000);
|
|
||||||
|
auto t1 = high_resolution_clock::now();
|
||||||
|
client mycli("localhost", 7000);
|
||||||
|
auto t2 = high_resolution_clock::now();
|
||||||
|
cout << "Connected: " << duration_cast<microseconds>(t2 - t1).count() << endl;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
sleep(4);
|
||||||
mycli.push("Helllo " + to_string(i++));
|
mycli.push("Helllo " + to_string(i++));
|
||||||
cout << mycli.pull() << endl;
|
cout << "> " << mycli.pull() << endl;
|
||||||
usleep(10000);
|
auto t3 = high_resolution_clock::now();
|
||||||
|
cout << "Sending and recive: " << duration_cast<microseconds>(t3 - t2).count() << endl;
|
||||||
|
// usleep(10000);
|
||||||
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// secure crypto;
|
// secure crypto;
|
||||||
|
BIN
test/client.o
BIN
test/client.o
Binary file not shown.
@ -62,27 +62,42 @@ int main() {
|
|||||||
// cli.push(fromclient);
|
// cli.push(fromclient);
|
||||||
// }, 200);
|
// }, 200);
|
||||||
|
|
||||||
server myserver(5000, 100);
|
server myserver(7000, 100);
|
||||||
myserver.pool(10, [](client &cli, mutex &io) {
|
// myserver.asyncPool(10, [](client &cli) {
|
||||||
cout << "Klijent " << cli.ipv4 << endl;
|
// cout << "Klijent " << cli.ipv4 << endl;
|
||||||
string fromclient = cli.pull();
|
// string fromclient = cli.pull();
|
||||||
// io.lock();
|
// // io.lock();
|
||||||
cout << "S klijenta " << fromclient << endl;
|
// cout << "S klijenta " << fromclient << endl;
|
||||||
// io.unlock();
|
// // io.unlock();
|
||||||
// fromclient += teststr;
|
// // fromclient += teststr;
|
||||||
usleep(10000);
|
// usleep(10000);
|
||||||
cli.push(fromclient);
|
// cli.push(fromclient);
|
||||||
}, 200);
|
// }, 200);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// string teststr = " Idemooo";
|
// string teststr = " Idemooo";
|
||||||
|
|
||||||
// myserver.sync([](client &cli) {
|
myserver.async(4, [](client &cli, mutex &io) {
|
||||||
// cout << "Klijent " << cli.ipv4 << endl;
|
while (true) {
|
||||||
// string fromclient = cli.pull();
|
try {
|
||||||
// cout << "S klijenta " << fromclient << endl;
|
string fromclient = cli.pull();
|
||||||
// // fromclient += teststr;
|
cout << "> " << fromclient << endl;
|
||||||
// cli.push(fromclient);
|
// fromclient += teststr;
|
||||||
// });
|
cli.push(fromclient);
|
||||||
|
} catch (const string err) {
|
||||||
|
cout << err << endl;
|
||||||
|
try {
|
||||||
|
cli.reconnect();
|
||||||
|
} catch (const string err) {
|
||||||
|
cout << err << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(const string err) {
|
catch(const string err) {
|
||||||
|
BIN
test/server.o
BIN
test/server.o
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user