Giter Site home page Giter Site logo

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

Contributors

skemo12 avatar irfan-ansari-au28 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.