Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03a8df4042 | ||
|
|
5fa791cf5e | ||
|
|
c030b22446 | ||
|
|
031853d8ee | ||
|
|
9217ce91c4 | ||
| 4388730e9f | |||
| 2118270646 | |||
|
|
043d0b26c6 | ||
|
|
e0feb8b2da | ||
|
|
65c2cdbbaf | ||
|
|
9e05ee86f7 | ||
|
|
7be0716f61 | ||
|
|
915975fba8 | ||
|
|
1f82e94296 | ||
|
|
b6468bd148 | ||
|
|
9e14e361e3 |
13
.vscode/settings.json
vendored
13
.vscode/settings.json
vendored
@ -44,6 +44,17 @@
|
|||||||
"stdexcept": "cpp",
|
"stdexcept": "cpp",
|
||||||
"streambuf": "cpp",
|
"streambuf": "cpp",
|
||||||
"cinttypes": "cpp",
|
"cinttypes": "cpp",
|
||||||
"typeinfo": "cpp"
|
"typeinfo": "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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,9 +4,16 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#if __linux__
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#elif _WIN32
|
||||||
|
// #include <sstream>
|
||||||
|
#include <WinSock.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|||||||
@ -3,17 +3,34 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
#if __linux__
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <openssl/ssl.h>
|
#elif _WIN32
|
||||||
#include <openssl/err.h>
|
#include <WinSock.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#pragma comment(lib,"ws2_32.lib")
|
||||||
|
#define ushort u_short
|
||||||
|
#define uint u_int
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "ip.hpp"
|
#include "ip.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
class client;
|
||||||
|
// class secure;
|
||||||
|
// class server;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server klasa za TCP/IP soket
|
* Server klasa za TCP/IP soket
|
||||||
* Instanca se incijalizira kada pokrećemo server
|
* Instanca se incijalizira kada pokrećemo server
|
||||||
@ -21,12 +38,25 @@ using namespace std;
|
|||||||
|
|
||||||
class server {
|
class server {
|
||||||
public:
|
public:
|
||||||
|
#if __linux__
|
||||||
int sock;
|
int sock;
|
||||||
|
#elif _WIN32
|
||||||
|
WSADATA wsa;
|
||||||
|
SOCKET sock;
|
||||||
|
#endif
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
|
SSL_CTX* securefds = NULL;
|
||||||
|
vector<thread> thr;
|
||||||
|
|
||||||
server (const ushort port, const uint limit = 1000);
|
server (const ushort port, const uint queue = 1000, SSL_CTX* _securefds = NULL);
|
||||||
~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 syncPool(void (*handlecli)(client&), const uint timeout = 100);
|
||||||
|
void asyncPool(const uint limit, void (*handlecli)(client&), const uint timeout = 100);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,40 +81,56 @@ class secure {
|
|||||||
|
|
||||||
class client {
|
class client {
|
||||||
public:
|
public:
|
||||||
int sock;
|
// zajedničke
|
||||||
|
#if __linux__
|
||||||
|
int conn; // mijenja sock
|
||||||
|
#elif _WIN32
|
||||||
|
WSADATA wsa;
|
||||||
|
SOCKET conn; // mijenja sock
|
||||||
|
#endif
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
SSL* ssl = NULL;
|
SSL* ssl = NULL;
|
||||||
|
string _address;
|
||||||
client (const string address, const ushort port, const uint timeout = 100, SSL_CTX* securefds = NULL);
|
ushort _port;
|
||||||
~client ();
|
uint _timeout;
|
||||||
bool tell (const string msg);
|
SSL_CTX* _securefds = NULL;
|
||||||
string obey (size_t byte_limit = 1024);
|
// server s klijentima
|
||||||
};
|
const server* srv = NULL;
|
||||||
|
// klijent sa serverom
|
||||||
|
|
||||||
/**
|
|
||||||
* Klasa za inicijalizaciju dolaznih veza
|
|
||||||
* Definira se na serverskom tipu aplikacija i predstavlja identifikator klijenta
|
|
||||||
*/
|
|
||||||
|
|
||||||
class comming {
|
|
||||||
public:
|
|
||||||
const server *srv;
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
int conn;
|
|
||||||
string ipv4;
|
string ipv4;
|
||||||
string ipv6;
|
string ipv6;
|
||||||
SSL* ssl = NULL;
|
|
||||||
|
|
||||||
comming(const server *_srv, const uint timeout = 100, SSL_CTX* securefds = NULL);
|
|
||||||
~comming();
|
|
||||||
bool tell (const string msg);
|
|
||||||
string obey (size_t byte_limit = 1024);
|
|
||||||
|
|
||||||
|
// konstruktor za klijente bez servera
|
||||||
|
client (const string address, const ushort port, const uint timeout = 100, SSL_CTX* securefds = NULL);
|
||||||
|
// konstruktor za klijente sa serverom
|
||||||
|
client (const server *_srv, const uint timeout = 100, SSL_CTX* securefds = NULL);
|
||||||
|
~client ();
|
||||||
|
bool push (const string msg);
|
||||||
|
string pull (size_t byte_limit = 1024);
|
||||||
|
bool reconnect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ustvari ne znam jel konekcija aktivna
|
||||||
|
* kod za connect i disconnect je konstruktoru - destruktoru
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class clientPool {
|
||||||
|
public:
|
||||||
|
mutex io;
|
||||||
|
uint numcli;
|
||||||
|
vector<pair<mutex*, client*>> drops;
|
||||||
|
|
||||||
|
// konstruktor za klijente bez servera
|
||||||
|
clientPool (const uint _numcli, const string address, const ushort port, const uint timeout = 100, SSL_CTX* securefds = NULL);
|
||||||
|
// konstruktor za klijente sa serverom
|
||||||
|
clientPool (const server *_srv, const uint _numcli, const uint timeout = 100, SSL_CTX* securefds = NULL);
|
||||||
|
~clientPool();
|
||||||
|
|
||||||
|
pair<mutex*, client*>* pickup();
|
||||||
|
void release(pair<mutex*, client*>* drop);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -4,12 +4,19 @@
|
|||||||
* Kontrustruktor varijable tipa server, prima port i limit za ograničenje liste klijenata na čekanju
|
* Kontrustruktor varijable tipa server, prima port i limit za ograničenje liste klijenata na čekanju
|
||||||
*/
|
*/
|
||||||
|
|
||||||
server::server (const ushort port, const uint limit) {
|
server::server (const ushort port, const uint queue, SSL_CTX* _securefds) {
|
||||||
|
securefds = _securefds;
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_addr.s_addr = INADDR_ANY;
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
addr.sin_port = htons(port);
|
addr.sin_port = htons(port);
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) {
|
||||||
|
throw string("[ERROR] WSA Startup. Detail: " + to_string(WSAGetLastError()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (sock <= 0) {
|
if (sock <= 0) {
|
||||||
throw string("[ERROR] Unable to open TCP socket ");
|
throw string("[ERROR] Unable to open TCP socket ");
|
||||||
@ -17,20 +24,126 @@ server::server (const ushort port, const uint limit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int opt=1;
|
int opt=1;
|
||||||
|
#if __linux__
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
|
||||||
throw string("[ERROR] Unable to set REUSEADDR or REUSEPORT on socket ");
|
throw string("[ERROR] Unable to set REUSEADDR or REUSEPORT on socket ");
|
||||||
}
|
}
|
||||||
|
#elif _WIN32
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt))) {
|
||||||
|
throw string("[ERROR] Unable to set REUSEADDR or REUSEPORT on socket ");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
|
if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
|
||||||
throw string("[ERROR] Unable to bind socket ");
|
throw string("[ERROR] Unable to bind socket ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(sock, limit) < 0) {
|
if (listen(sock, queue) < 0) {
|
||||||
throw string("[ERROR] It is not possible to set the allowed number of waiting clients ");
|
throw string("[ERROR] It is not possible to set the allowed number of waiting clients ");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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::sync(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::async(const uint limit, void (*handlecli)(client&, mutex&), const uint timeout) {
|
||||||
|
mutex io;
|
||||||
|
// do {
|
||||||
|
for (uint i=0; i<limit; i++) {
|
||||||
|
thr.push_back(thread([&](){
|
||||||
|
client *cli = new client(this, timeout, securefds);
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
handlecli(*cli, io);
|
||||||
|
} catch (const string err) {
|
||||||
|
cout << err << endl;
|
||||||
|
cli->~client();
|
||||||
|
cli = new client(this, timeout, securefds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i=0; i<limit; i++) {
|
||||||
|
thr[i].join();
|
||||||
|
}
|
||||||
|
// thr.clear();
|
||||||
|
|
||||||
|
// } while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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( [&]() {
|
||||||
|
pair<mutex*, client*>* cli = clipool.pickup();
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
handlecli(*(cli->second));
|
||||||
|
} catch (const string err) {
|
||||||
|
cout << err << endl;
|
||||||
|
cli->second->~client();
|
||||||
|
cli->second = new client(this, timeout, securefds);
|
||||||
|
}
|
||||||
|
clipool.release(cli);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i=0; i<limit; i++) {
|
||||||
|
thr[i].join();
|
||||||
|
}
|
||||||
|
thr.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destruktor varijable tipa server
|
* Destruktor varijable tipa server
|
||||||
*/
|
*/
|
||||||
@ -42,10 +155,21 @@ server::~server () {
|
|||||||
throw string("[ERROR] The socket is already closed ");
|
throw string("[ERROR] The socket is already closed ");
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (close(sock) != 0) {
|
else {
|
||||||
|
|
||||||
|
#if __linux__
|
||||||
|
if (close(sock) != 0) {
|
||||||
throw string("[ERROR] Unable to close socket ");
|
throw string("[ERROR] Unable to close socket ");
|
||||||
}
|
}
|
||||||
|
#elif _WIN32
|
||||||
|
if (closesocket(sock) != 0) {
|
||||||
|
throw string("[ERROR] Unable to close socket ");
|
||||||
|
}
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,8 +234,14 @@ secure::~secure () {
|
|||||||
|
|
||||||
client::client(const string address, const ushort port, const uint timeout, SSL_CTX* securefds) {
|
client::client(const string address, const ushort port, const uint timeout, SSL_CTX* securefds) {
|
||||||
|
|
||||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
#if _WIN32
|
||||||
if (sock < 0) {
|
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 ");
|
throw string("[ERROR] Unable to open TCP socket ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,24 +251,31 @@ client::client(const string address, const ushort port, const uint timeout, SSL_
|
|||||||
addr.sin_addr.s_addr = inet_addr(_address.c_str());
|
addr.sin_addr.s_addr = inet_addr(_address.c_str());
|
||||||
addr.sin_port = htons(port);
|
addr.sin_port = htons(port);
|
||||||
|
|
||||||
if (connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) != 0) {
|
if (connect(conn, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) != 0) {
|
||||||
throw string("Unable to connect to server ");
|
throw string("Unable to connect to server ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __linux__
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
tv.tv_sec = timeout/1000;
|
tv.tv_sec = timeout/1000;
|
||||||
tv.tv_usec = (timeout%1000)*1000;
|
tv.tv_usec = (timeout%1000)*1000;
|
||||||
|
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval))) {
|
if (setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval))) {
|
||||||
throw string("[ERROR] Unable to set timeout ");
|
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) {
|
if (securefds) {
|
||||||
ssl = SSL_new(securefds);
|
ssl = SSL_new(securefds);
|
||||||
if (!ssl) {
|
if (!ssl) {
|
||||||
throw string("[ERROR] Creating SSL object ");
|
throw string("[ERROR] Creating SSL object ");
|
||||||
}
|
}
|
||||||
SSL_set_fd(ssl, sock);
|
SSL_set_fd(ssl, conn);
|
||||||
|
|
||||||
// Perform the SSL handshake
|
// Perform the SSL handshake
|
||||||
if (SSL_connect(ssl) <= 0) {
|
if (SSL_connect(ssl) <= 0) {
|
||||||
@ -150,65 +287,6 @@ client::client(const string address, const ushort port, const uint timeout, SSL_
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destruktor varijable tipa client
|
|
||||||
*/
|
|
||||||
|
|
||||||
client::~client () {
|
|
||||||
|
|
||||||
if (ssl) {
|
|
||||||
SSL_shutdown(ssl);
|
|
||||||
SSL_free(ssl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sock <= 0) {
|
|
||||||
throw string("[ERROR] The socket is already closed ");
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (close(sock) != 0) {
|
|
||||||
throw string("[ERROR] Unable to close socket ");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metoda klase client za slanje podataka preko soketa
|
|
||||||
* Prima string koji će biti poslan
|
|
||||||
* Vraća logički statu poređenja psolanih karaktera i karaktera u stringu
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
bool client::tell (const string msg) {
|
|
||||||
size_t sended = 0;
|
|
||||||
if (ssl) {
|
|
||||||
sended = SSL_write(ssl, msg.c_str(), msg.length());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sended = write(sock, msg.c_str(), msg.length());
|
|
||||||
}
|
|
||||||
return sended == msg.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metoda klase client za primanje poruke preko soketa
|
|
||||||
* Prima dozvoljeni broj karaktera koji će primiti
|
|
||||||
* Vraća string primljene poruke
|
|
||||||
*/
|
|
||||||
|
|
||||||
string client::obey (size_t byte_limit) {
|
|
||||||
char res[byte_limit] = {0};
|
|
||||||
|
|
||||||
if (ssl) {
|
|
||||||
SSL_read(ssl, res, byte_limit);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
read(sock , res, byte_limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Konstruktor varijable tipa commint
|
* Konstruktor varijable tipa commint
|
||||||
* Prima pokazivač na inicijaliziranu varijablu tipa, port,
|
* Prima pokazivač na inicijaliziranu varijablu tipa, port,
|
||||||
@ -217,7 +295,7 @@ string client::obey (size_t byte_limit) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
comming::comming(const server *_srv, const uint timeout, SSL_CTX* securefds) {
|
client::client(const server *_srv, const uint timeout, SSL_CTX* securefds) {
|
||||||
srv = _srv;
|
srv = _srv;
|
||||||
socklen_t len = sizeof(struct sockaddr_in);
|
socklen_t len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
@ -225,6 +303,7 @@ comming::comming(const server *_srv, const uint timeout, SSL_CTX* securefds) {
|
|||||||
throw string("[ERROR] Unable to accept client connection ");
|
throw string("[ERROR] Unable to accept client connection ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __linux__
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
tv.tv_sec = timeout/1000;
|
tv.tv_sec = timeout/1000;
|
||||||
tv.tv_usec = (timeout%1000)*1000;
|
tv.tv_usec = (timeout%1000)*1000;
|
||||||
@ -232,6 +311,15 @@ comming::comming(const server *_srv, const uint timeout, SSL_CTX* securefds) {
|
|||||||
if (setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval))) {
|
if (setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval))) {
|
||||||
throw string("[ERROR] Unable to set timeout ");
|
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) {
|
if (securefds) {
|
||||||
@ -259,11 +347,12 @@ comming::comming(const server *_srv, const uint timeout, SSL_CTX* securefds) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destruktor varijable tipa comming
|
* Destruktor varijable tipa client
|
||||||
*/
|
*/
|
||||||
|
|
||||||
comming::~comming() {
|
client::~client () {
|
||||||
|
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
SSL_shutdown(ssl);
|
SSL_shutdown(ssl);
|
||||||
@ -274,44 +363,246 @@ comming::~comming() {
|
|||||||
throw string("[ERROR] The socket is already closed ");
|
throw string("[ERROR] The socket is already closed ");
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (close(conn) != 0) {
|
else {
|
||||||
|
#if __linux__
|
||||||
|
if (close(conn) != 0) {
|
||||||
throw string("[ERROR] Unable to close socket ");
|
throw string("[ERROR] Unable to close socket ");
|
||||||
}
|
}
|
||||||
|
#elif _WIN32
|
||||||
|
if (closesocket(conn) != 0) {
|
||||||
|
throw string("[ERROR] Unable to close socket ");
|
||||||
|
}
|
||||||
|
//WSACleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metoda klase comming za slanje podataka preko soketa
|
* Metoda klase client za slanje podataka preko soketa
|
||||||
* Prima string koji će biti poslan
|
* Prima string koji će biti poslan
|
||||||
* Vraća logički statu poređenja psolanih karaktera i karaktera u stringu
|
* Vraća logički statu poređenja psolanih karaktera i karaktera u stringu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool comming::tell (const string msg) {
|
|
||||||
ssize_t sended = 0;
|
bool client::push(const string msg) {
|
||||||
|
size_t total_sent = 0;
|
||||||
|
size_t msg_length = msg.length();
|
||||||
|
|
||||||
|
while (total_sent < msg_length) {
|
||||||
|
size_t sent = 0;
|
||||||
|
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
sended = SSL_write(ssl, msg.c_str(), msg.length());
|
sent = SSL_write(ssl, msg.c_str() + total_sent, msg_length - total_sent);
|
||||||
}
|
} else {
|
||||||
else {
|
sent = send(conn, msg.c_str() + total_sent, msg_length - total_sent, 0);
|
||||||
sended = write(conn, msg.c_str(), msg.length());
|
|
||||||
}
|
|
||||||
return sended == msg.length();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sent == -1) {
|
||||||
|
// Greška pri slanju poruke
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_sent += sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metoda klase comming za primanje poruke preko soketa
|
* Metoda klase client za primanje poruke preko soketa
|
||||||
* Prima dozvoljeni broj karaktera koji će primiti
|
* Prima dozvoljeni broj karaktera koji će primiti
|
||||||
* Vraća string primljene poruke
|
* Vraća string primljene poruke
|
||||||
*/
|
*/
|
||||||
|
|
||||||
string comming::obey (size_t byte_limit) {
|
string client::pull(size_t byte_limit) {
|
||||||
char res[byte_limit] = {0};
|
char res[byte_limit] = {0};
|
||||||
|
size_t total_received = 0;
|
||||||
|
|
||||||
|
while (total_received < byte_limit) {
|
||||||
|
ssize_t received = 0;
|
||||||
|
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
SSL_read(ssl, res, byte_limit);
|
received = SSL_read(ssl, res + total_received, byte_limit - total_received);
|
||||||
|
} else {
|
||||||
|
received = recv(conn, res + total_received, byte_limit - total_received, 0);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
read(conn , res, byte_limit);
|
if (received == -1) {
|
||||||
|
// Greška pri primanju poruke
|
||||||
|
cout << "Da vidim jel ovdje kad nije poslo " << endl;
|
||||||
|
break;
|
||||||
|
} else if (received == 0) {
|
||||||
|
// Veza je prekinuta - treba pozvati destruktor
|
||||||
|
// cout << "Destruktor " << endl;
|
||||||
|
// this->~client();
|
||||||
|
throw string("[WARNING] Socket closed remotely");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_received += received;
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(res);
|
return string(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool client::reconnect() {
|
||||||
|
if (_address.empty() && srv != NULL) {
|
||||||
|
// srv = _srv;
|
||||||
|
socklen_t len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
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 ) {
|
||||||
|
numcli = _numcli;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw string("[ERROR] Invalid number of instances in pool ");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i=0; i<numcli; i++) {
|
||||||
|
drops.push_back(make_pair(new mutex, new client(address, port, timeout, securefds)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
clientPool::clientPool(const server *_srv, const uint _numcli, const uint timeout, SSL_CTX* securefds) {
|
||||||
|
if (_numcli > 1 ) {
|
||||||
|
numcli = _numcli;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw string("[ERROR] Invalid number of instances in pool ");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i=0; i<numcli; i++) {
|
||||||
|
cout << "init clients " << i << endl;
|
||||||
|
drops.push_back(make_pair(new mutex, new client(_srv, timeout, securefds)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
drops.clear();
|
||||||
|
|
||||||
|
}
|
||||||
106
test/client.cpp
106
test/client.cpp
@ -1,26 +1,116 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#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() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
secure crypto;
|
// uint n = 10000;
|
||||||
cout << "init cert " << endl;
|
|
||||||
|
|
||||||
client myserver("127.0.0.1", 5000, 5000, crypto.fds);
|
// vector<thread> thr;
|
||||||
|
// for (uint i=0; i<n; i++) {
|
||||||
|
// thr.push_back(thread([](uint a){
|
||||||
|
// client myserver("127.0.0.1", 5000, 500);
|
||||||
|
// string sends = "Hello world " + to_string(a);
|
||||||
|
// myserver.push(sends);
|
||||||
|
// cout << myserver.pull() << endl;
|
||||||
|
// }, i));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (uint i=0; i<n; i++) {
|
||||||
|
// thr[i].join();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// uint i = 0;
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
// t2 = high_resolution_clock::now();
|
||||||
|
// mycli.push("Helllo " + to_string(i++));
|
||||||
|
// cout << "> " << mycli.pull() << endl;
|
||||||
|
// auto t3 = high_resolution_clock::now();
|
||||||
|
// cout << "Sending and recive: " << duration_cast<microseconds>(t3 - t2).count() << endl;
|
||||||
|
// // usleep(10000);
|
||||||
|
// }
|
||||||
|
|
||||||
|
clientPool clies(5, "localhost", 7000);
|
||||||
|
|
||||||
|
thread t1([&]() {
|
||||||
|
int i = 0;
|
||||||
|
while (true) {
|
||||||
|
auto t1 = high_resolution_clock::now();
|
||||||
|
auto socks = clies.pickup();
|
||||||
|
auto t2 = high_resolution_clock::now();
|
||||||
|
cout << "Picking : " << duration_cast<microseconds>(t2 - t1).count() << endl;
|
||||||
|
socks->second->push("Helllo I " + to_string(i++));
|
||||||
|
cout << "> " << socks->second->pull() << endl;
|
||||||
|
auto t3 = high_resolution_clock::now();
|
||||||
|
cout << "Sending and recive: " << duration_cast<microseconds>(t3 - t2).count() << endl;
|
||||||
|
clies.release(socks);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
thread t2([&]() {
|
||||||
|
int i = 0;
|
||||||
|
while (true) {
|
||||||
|
auto t1 = high_resolution_clock::now();
|
||||||
|
auto socks = clies.pickup();
|
||||||
|
auto t2 = high_resolution_clock::now();
|
||||||
|
cout << "Picking : " << duration_cast<microseconds>(t2 - t1).count() << endl;
|
||||||
|
socks->second->push("Helllo II " + to_string(i++));
|
||||||
|
cout << "> " << socks->second->pull() << endl;
|
||||||
|
auto t3 = high_resolution_clock::now();
|
||||||
|
cout << "Sending and recive: " << duration_cast<microseconds>(t3 - t2).count() << endl;
|
||||||
|
clies.release(socks);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
thread t3([&]() {
|
||||||
|
int i = 0;
|
||||||
|
while (true) {
|
||||||
|
auto t1 = high_resolution_clock::now();
|
||||||
|
auto socks = clies.pickup();
|
||||||
|
auto t2 = high_resolution_clock::now();
|
||||||
|
cout << "Picking : " << duration_cast<microseconds>(t2 - t1).count() << endl;
|
||||||
|
socks->second->push("Helllo III " + to_string(i++));
|
||||||
|
cout << "> " << socks->second->pull() << endl;
|
||||||
|
auto t3 = high_resolution_clock::now();
|
||||||
|
cout << "Sending and recive: " << duration_cast<microseconds>(t3 - t2).count() << endl;
|
||||||
|
clies.release(socks);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
t1.join();
|
||||||
|
t2.join();
|
||||||
|
t3.join();
|
||||||
|
|
||||||
|
// secure crypto;
|
||||||
|
// cout << "init cert " << endl;
|
||||||
|
|
||||||
|
// client myserver("127.0.0.1", 5000, 5000, crypto.fds);
|
||||||
|
// client myserver("localhost", 8000, 5000, crypto.fds);
|
||||||
// client myserver("localhost", 5000);
|
// client myserver("localhost", 5000);
|
||||||
cout << "init client " << endl;
|
// cout << "init client " << endl;
|
||||||
|
|
||||||
|
|
||||||
string sends = "Hello world!";
|
// string sends = "Hello world!";
|
||||||
cout << myserver.tell(sends) << " " << sends.length() << endl;
|
// cout << myserver.push(sends) << " " << sends.length() << endl;
|
||||||
cout << "wait client " << endl;
|
// cout << "wait client " << endl;
|
||||||
|
|
||||||
cout << myserver.obey();
|
// cout << myserver.pull();
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (const string err) {
|
catch (const string err) {
|
||||||
|
|||||||
BIN
test/client.exe
Normal file
BIN
test/client.exe
Normal file
Binary file not shown.
BIN
test/client.o
BIN
test/client.o
Binary file not shown.
1
test/compile-client.ps1
Normal file
1
test/compile-client.ps1
Normal file
@ -0,0 +1 @@
|
|||||||
|
g++ client.cpp ../src/* -o client.exe -lssl -lcrypto -lws2_32
|
||||||
1
test/compile-server.ps1
Normal file
1
test/compile-server.ps1
Normal file
@ -0,0 +1 @@
|
|||||||
|
g++ server.cpp ../src/* -o server.exe -lssl -lcrypto -lws2_32
|
||||||
@ -1 +1 @@
|
|||||||
g++ server.cpp ../src/* -o server.o -lssl -lcrypto
|
g++ server.cpp ../src/* -o server.o -lssl -lcrypto -lpthread
|
||||||
@ -6,21 +6,36 @@ using namespace std;
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
try{
|
try{
|
||||||
cout << "init server " << endl;
|
// cout << "init cert " << endl;
|
||||||
server myserver(5000);
|
// secure crypto ("../example/cert.pem", "../example/privkey.pem");
|
||||||
cout << "init cert " << endl;
|
// cout << "init server " << endl;
|
||||||
secure crypto ("../example/cert.pem", "../example/privkey.pem");
|
// server myserver(5000, 100, crypto.fds);
|
||||||
cout << "init client " << endl;
|
// cout << "init cert " << endl;
|
||||||
|
// secure crypto ("../example/cert.pem", "../example/privkey.pem");
|
||||||
|
// cout << "init server " << endl;
|
||||||
|
// server myserver(8000, 100, crypto.fds);
|
||||||
|
|
||||||
comming myclient(&myserver, 100, crypto.fds);
|
// cout << "init client " << endl;
|
||||||
// comming myclient(&myserver, 100);
|
|
||||||
cout << "wait client " << myclient.ipv4 << endl;
|
|
||||||
|
|
||||||
string fromclient = myclient.obey();
|
// // client myclient(&myserver, 100, crypto.fds);
|
||||||
cout << "tell client " << fromclient << endl;
|
// // comming myclient(&myserver, 100);
|
||||||
|
// myserver.accept();
|
||||||
|
// // cout << "wait client " << myclient.ipv4 << endl;
|
||||||
|
// cout << "wait client " << myserver.cli->ipv4 << endl;
|
||||||
|
|
||||||
|
// string fromclient = myserver.cli->pull();
|
||||||
|
// // string fromclient = myclient.pull();
|
||||||
|
// cout << "tell client " << fromclient << endl;
|
||||||
|
// // usleep(600*1000);
|
||||||
|
// sleep(5);
|
||||||
|
// myserver.cli->push(fromclient);
|
||||||
|
// string fromclient = myserver.cli->pull();
|
||||||
|
// string fromclient = myclient.pull();
|
||||||
|
// cout << "tell client " << fromclient << endl;
|
||||||
// usleep(600*1000);
|
// usleep(600*1000);
|
||||||
sleep(5);
|
//sleep(5);
|
||||||
myclient.tell(fromclient);
|
// myserver.cli->push(fromclient);
|
||||||
|
// myclient.push(fromclient);
|
||||||
// myclient.~comming();
|
// myclient.~comming();
|
||||||
|
|
||||||
// while (true) {
|
// while (true) {
|
||||||
@ -33,6 +48,48 @@ int main() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// sleep(80);
|
// sleep(80);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
// cli.push(fromclient);
|
||||||
|
// }, 200);
|
||||||
|
|
||||||
|
server myserver(7000, 100);
|
||||||
|
// myserver.asyncPool(10, [](client &cli) {
|
||||||
|
// cout << "Klijent " << cli.ipv4 << endl;
|
||||||
|
// string fromclient = cli.pull();
|
||||||
|
// // io.lock();
|
||||||
|
// cout << "S klijenta " << fromclient << endl;
|
||||||
|
// // io.unlock();
|
||||||
|
// // fromclient += teststr;
|
||||||
|
// usleep(10000);
|
||||||
|
// cli.push(fromclient);
|
||||||
|
// }, 200);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// string teststr = " Idemooo";
|
||||||
|
|
||||||
|
myserver.async(4, [](client &cli, mutex &io) {
|
||||||
|
while (true) {
|
||||||
|
string fromclient = cli.pull();
|
||||||
|
cout << "> " << fromclient << endl;
|
||||||
|
// fromclient += teststr;
|
||||||
|
cli.push(fromclient);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(const string err) {
|
catch(const string err) {
|
||||||
cout << err << endl;
|
cout << err << endl;
|
||||||
|
|||||||
BIN
test/server.exe
Normal file
BIN
test/server.exe
Normal file
Binary file not shown.
BIN
test/server.o
BIN
test/server.o
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user