server-client-requests-tcp-udp's Introduction
-- Tema 2 PCom-- Paunoiu Darius Alexandru -- 322CD -- README Tema este rezolvata integral, rezolvarea gasindu-se in 3 fisiere: - server.cpp - subscriber.cpp - helpers.h Am ales sa rezolv tema in C++ pentru a beneficia de structurile de date si de functionalele din acest limbaj. Toate functiile, campurile, si clasele sunt descrise in cod prin comentarii, dar voi detalia anumite aspecte mai importante si in acest README. Biblioteca helpers.h contine structuri constante si functii utile folosite atat de subscriber cat si de server. Toate sunt explicate prin comentarii. Serverul primeste urmatoare tipuri de pachete prin socketii definiti: 1. Comenzi de la subscribers, de tipul subscribe, unsubscribe si exit, pentru care am defenit structura command 2. Pachete de la clientii UDP, pentru care am defenit structura udp_message 3. Cereri de conectare, care sunt acceptate daca ID-ul este unic. ID-ul este obtinut tot prin intermediul structurii command. De asemenea, serverul primeste date de intrare si prin STDIN, acceptand ca mesaj valid doar mesajul de "exit". Pentru alte mesaje va afisa la stderr mesajul "Invalid input.\n". Subscriberul poate primi doar un tip de pachete pe socket-ul TCP pe care realizeaza conexiunea la server: - un pachet de tipul server_message, interpretat cu ajutorul structurii cu acelasi nume. Acesta contine datele clientului UDP care a trimis mesajul, cat si mesajul trimit sub structura de udp_message, aceeasi ca cea definita pentru server. El contine si lungimea pachetului. De asemenea, subscriberul accepta si comenzi de la tastatura, comenzile valide fiind cele definite in enunt. Pentru o comanda invalida se va afisa mesajul "Not a valid input command.\n" la stderr. Desi serverul foloseste structura udp_message, acesta nu interpreteaza din mesajul primit decat campul topic. Interpretarea continutului unui pachet ( campul content) in functie de tipul de date se face de catre subscriber. Am ales aceasta implemtare datorita urmatoarelor motive: - se reduce timpul necesar parsarii unui mesaj de la clientul UDP pentru server. Deoarece fiecare subscriber isi interpreteaza singur pachetele, aceasta munca este impartita pe toti clientii abonati la acel topic, iar serverul nu mai trebui sa faca acest lucru, scazand latenta primirii mesajelor de catre subscriber. - in cazul in care se doreste o encriptare a mesajelor de tipul END-to-END, serverul nu ar trebui sa stie decat topic-ul la care un client este abonat, neavand accest la continut. Serverul mai foloseste 2 clase dedicate lui, acestea fiind: - clasa Topic, ce este folosita pentru descrierea unui topic. aceasta clasa are 2 atribute si nicio metoda. Am ales sa descriu topic-ul cu o clasa in locul unui structuri pentru ca aceasta metoda este mai fezabila pentru termen lung, fiind usor de adaugat mai multe functionalitati la aceasta clasa in caz ca este nevoie. - clasa Subscriber, care descrie in intregime un subscriber. Aceasta are mai multe atribute si metode, toate fiind descrise cu comentarii in cod. Totodata, pentru a fii mai rapid, socket-ul nu face parcugerea clasica pentru select, de la i = 0 la i -> fdmax, ci verifica doar socketii clientilor salvati. Pentru a asigura primirea mesajelor intregi (nu concatenate sau incomplete), m-am folosit de structura server_message, ce salveaza lungimea unui mesaj in functie de tipul de date pe care il primeste. (De exemplu, pentru int, din cei 1500 de octeti din content, se folosesc doar 5 octeti, deci pentru tipul 0 avem 5 octeti). Numarul de octeti necesar este dat de functie bytes_needed. La primul recv, vom primi cei 4 octeti ce reprezinta dimensiunea pachetului, dupa care repetam recv pana avem exact number_of_bytes octeti primiti (la fiecare pas, scadem numarul de octeti ce pot fi primiti, numarul fiind diferenta dintre numarul de octeti ce trebuie primiti, adica number_of_bytes, si numarul de octeti primiti pana in acel moment.) De asemenea, pentru a ne asigura ca nu primim mai mult de un mesaj, la fiecare receive pe socketul ce este conectat la server, vom primi initial 4 octeti, dupa care restul de octeti. Pentru mesajele de la client la server, m-am folosit de structura command. Abordarea este similara cu cea pentru server_message. Initial primim maxim 4 octeti, dupa care restul de octeti. Dimensiunea mesajului este de maxim 65 de octeti (50 numele topicului, + cuvantul subscribe si tagul sf sau unsubscribe). Totusi, aceasta este dimensiunea maxima,si sunt trimisi doar cati octeti sunt necesari. De asemenea, pentru trimite id-ul unui client, se va trimite un mesaj de tipul command cu numarul de octeti trimisi egala cu lungimea ID-ului + restul de octeti necesari. Pentru stocarea implicita a datelor, serverul foloseste 2 hashmap-uri. Unul este folosit pentru a creea o asociere socket -> date client. Acesta este foarte util pentru a afla usor datele unui client in functie de socket, de exemplu atunci cand un client se inchide, ii cunoastem socketul si avem nevoi de ID-ul lui. Al doilea hashmap este folosit pentru a creea o asociere nume_topic -> pointer la datele clientilor abonati la acel topic. Acesta din urma este foarte util atunci cand trebuie trimit un mesaj la fiecare client abonat la un topic, doarecere evitam o cautare liniara in lista de clienti, ceea ce reduce foarte mult timpul necesar trimiterii mesajelor, in special cand aplicatia ar fi incarcata cu foarte multi clienti care sunt abonati la foarte multe topicuri, si dorim o cautare mai buna decat una liniara. Dezavantajul la aceasta metoda este memoria necesara, deoarece folosirea a doua hashmap-uri este mai costisitoare comparativ cu folosirea unui singur hashmap. Totusi, aceasta metoda poate ramane eficienta in cazul implementarii stocarii datelor in fisiere, pentru a nu supra solicita memoria RAM. Am ales sa folosesc 2 hashmap-uri deoarece in enunt s-a specificat ca putem considera ca server-ul va avea suficienta memoria RAM, iar acest lucru m-a dus cu gandul la serverele mari, care au in bazele lor de date multiple hashmap-uri. Toate constantele si structurile folosite atat la trimitere cat si la primire, sunt explicate cu comentarii. Tema urmeaza o abordare cat mai eficienta posibila, atat din punctul de vedere al timpului cat si al memoriei folosite, dar se axeaza mai mult pe reducurea latentei. Mentionez ca am tinut fiecare linie mai mica de 80 de caractere, si am incercat sa tin dimensiunea functiilor cat mai mica posibil. Acolo unde nu am introdus o functie (de exemplu, fiecare continut al unui if din main putea sa fie o functie), este pentru ca numarul necesar de parametrii ar fi fost foarte mare, lucru ce cel putin din cunostintele mele de IOCLA, de multe ori nu este eficient, deoarece peste 8 argumente la o functie, se va folosi stiva pentru parsarea lor, iar stiva este lenta. Va multumesc pentru atentie si feedback!
server-client-requests-tcp-udp's People
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.