Skip to content

Eteriss/chat_client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

IPK Projekt 1: Klient pre chatovací server

Cieľom projektu bolo vytvoriť klienta pre chatovací server na komunikáciu pomocou protokolu UDP a TCP. Program umožňuje výmenu správ medzi klientom a serverom a podporuje rôzne typy správ, ako sú autentifikácia, potvrdenia, odpovede, chybové správy a ukončenie spojenia.

Obsah

Teória

Aplikácia využíva protokoly TCP (Transmission Control Protocol) a UDP (User Datagram Protocol) na komunikáciu s serverom. TCP zabezpečuje spoľahlivé spojenie s garanciou doručenia a poradia prenášaných správ, zatiaľ čo UDP poskytuje jednoduchý prenos bez spojenia s nižšou režiou, ale bez záruky doručenia alebo poradia. Tieto protokoly sú využívané pre vytvorenie, prenos a ukončenie spojenia medzi klientom a serverom, čo umožňuje efektívnu a spoľahlivú komunikáciu medzi nimi. Vo funkcionalite programu sa správy, ktoré sú reprezentované triedami správ, prevádzajú na pole bytov, aby mohli byť odoslané pomocou príslušného transportného protokolu. V prípade UDP je tento proces vykonávaný priamo, zatiaľ čo v prípade TCP je najprv vytvorené spojenie s serverom prostredníctvom TcpClient, po ktorom sú správy odosielané a prijímané.

Štruktúra projektu

IPK_Project1/
├── Tcp/
│   ├── TcpMessage.cs
│   └── TcpTransport.cs
├── Udp/
│   ├── MessageType.cs
│   ├── UdpMessage.cs
│   └── UdpTransport.cs
├── ErrorType.cs
├── Program.cs
└── User.cs

Program.cs:

Predstavuje vstupný bod programu. Vo funkcii ParseArguments sa spracujú a skontrolujú argumenty a následne sa na základe zadaného transportu začne vykonávať tcp alebo udp vetva. Obidva transporty sú rozdelené na dve vlákna, ktoré pracujú paralelne - ProcessUserInputTcp, ProcessReceivedMessagesTcp resp. ProcessUserInputUdp, ProcessReceivedMessagesUdp. Prvé vlákno čaká na vstup od uživateľa a vo funkcii ExecuteCommand, ktorá je spoločná pre obidva transporty, vykonáva zadané príkazy. Druhé vlákno čaká na prichádzajúce správy od serveru. Ak sa v akomkoľvek stave obdrží správa typu error alebo neočkávaný typ správy, pošle sa bye a program sa ukončí. Program sa tiež ukončí ak na vstup príde EOF pri špecifikovaní súboru, z ktorého sa majú čítať príkazy alebo ak uživateľ stlačí ctrl-c.

User.cs:

Trieda obsahuje metódu ValidateAuth na overenie argumentov príkazu auth a metódu WriteHelpMessage na výpis nápovedy.

ErrorType.cs:

Definuje enum ErrorType, ktorý obsahuje typy chýb, ktoré môžu nastať v rámci implementácie projektu.

Tcp

TcpMessage.cs:

Určuje triedu TcpMessage, ktorá predstavuje TCP správy. Obsahuje typ správy, ktorý má každá správa, a ďalej vlastnosti, ktoré sú pridelené podla typu správy - informácie o odpovedi, zobrazovacie meno osoby a obsah správy.

TcpTransport.cs:

Zavádza triedu TcpTransport, ktorá spravuje komunikáciu pomocou TCP, kde sa v TcpClientInit vytvára spojenie so serverom. Metóda ReceiveMessage prijíma správu zo servera a vytvára inštanciu triedy TcpMessage. V metóde CheckMessageSyntax sa skontroluje syntax prijatej správy a na základe jej typu potom priradí hodnoty do potrebných atributov.

Udp

UdpMessage.cs:

V subore sa nachádzajú triedy a rozhranie, ktoré predstavujú rôzne typy správ používaných pri komunikácii. Patrí sem rozhranie IMessage, ktoré určuje spoločné vlastnosti správ (typ a id) a konkrétne triedy pre špecifické typy správ, ako sú autentifikácia (AuthMessage), potvrdenia (ConfirmMessage), chybové správy (ErrorMessage), atď.

MessageType.cs:

Obsahuje enum MessageType, ktorý definuje všetky typy používaných správ, kde každý typ je reprezentovaný jedným bytom.

UdpTransport.cs:

Zavádza triedu UdpTransport, ktorá spravuje komunikáciu pomocou UDP a riadi výmenu správ medzi klientom a serverom. V triede sa nachádza metóda MessageToByteArray, ktorá prevádza správu na odoslanie na bytové pole a metóda ByteArrayToMessage, ktorá na základe prijatých bytov vráti inštanciu konkrétnej správy. Spojenie so serverom sa nadväzuje v metóde UdpClientInit po zadaní príkazu auth. Odosielanie a asynchrónne prijímanie správ a overenie, že správa bola serverom prijatá zaisťujú metódy SendMessage a ReceiveMessage. Udp komunikácia vyžaduje aby bola každá prijatá správa potvrdená odoslaním správy typu confirm druhou stranou. Po odoslaní správy v SendMessage sa teda čaká (v základe maximálne trikrát 250ms) na potvrdzujúcu správu od serveru a ak nepríde, odošle sa správa znova. Uživateľ môže pri spúštaní programu zadať, ako dlho sa má na confirm čakať a kolkokrát má program správu skúsiť odoslať znova (premenná MaxRetries) ak confirm neobdrží. Po uplynutí času na prijatie sa program ukončí s chybou. Na každú prijatú správu, ktorá nie je typu confirm sa v metóde SendConfirmMessage odošle potvrdzujúca správa. Ak bola v akomkoľvek stave prijatá správa typu error, spojenie so serverom sa v ReceivedErrorMessage preruší a program sa ukončí.

UML diagram

UML_DIAGRAM

Zaujímavé časti kódu

V tejto časti sa zameriam na podrobnú analýzu a vysvetlenie niektorých kľúčových častí programu.

public async Task SendMessage(IMessage message) {
     WaitingForConfirm = true;
     IncrementId(message);
     MessageToSend = message;
     byte[] messageToSend = MessageToByteArray(message);

     for (int i = 0; i < MaxRetries; i++) {
           if (UdpClient.Client.Connected) 
              await UdpClient.SendAsync(messageToSend, messageToSend.Length);
           else
              await UdpClient.SendAsync(messageToSend, messageToSend.Length, EndPoint);
            
           await Task.Delay(Delay);
           if (!WaitingForConfirm) {
              return; //received confirm message
           }
     }

     await Console.Error.WriteLineAsync("ERR: No response from server.");
     Environment.Exit((int)ErrorType.NoResponse);
}

Metóda SendMessage v udp protokole je hlavnou funkciou na odosielanie správ a kontrolu či bola prijatá confirm správa. Po nastavení flagu WaitingForConfirm a prevedení správy na bytové pole sa spúšťa cyklus, ktorý odosiela správu serveru. Ak ide o prvú správu a klient ešte nie je pripojený uvádza sa aj EndPoint kam má správu zaslať. Následne sa čaká 250ms (ak uživateľ nešpecifikoval inak). Ak sa počas tohoto čakania v druhom vlákne prijíme confirm správa, nastaví sa WaitingForConfirm flag na false a metóda sa ukončí. V prípade, že program potvrdzujúcu správu neprijíme, sa správa odošle znova. Ak sa nepríjme ani po MaxRetries, program sa ukončí s chybou.

Queue<string?> commandQueue = new Queue<string?>();
udpTransport.StatusChanged += async (_, args) =>
{
    if (!args.WaitingForReply && !args.WaitingForConfirm)
    {
        while (commandQueue.Count != 0)
        {
            if(udpTransport.WaitingForReply || udpTransport.WaitingForConfirm)
                break;
            
            string? input = commandQueue.Dequeue();
            await ExecuteCommand(input, udpTransport, null, true);
        }
    }
};
if (commandQueue.Count > 0 || udpTransport.WaitingForReply || udpTransport.WaitingForConfirm && command != "/rename" && command != "/help")
{
     commandQueue.Enqueue(input);
     continue;
}

Ak uživateľ zadá príkaz, na ktorý sa očakáva od serveru správa typu reply (v udp aj confirm) a pred tým ako túto správu obdrží, zadá ďalšie príkazy, sa tieto príkazy vkladajú do rady commandQueue. Event handler StatusChanged sa potom zavolá vždy, keď sa očakávaná správa prijme (premenná WaitingForReply a WaitingForConfirm sa nastaví na false) a vykoná všetky príkazy, ktoré boli vložené do rady.

Testovanie

Testovanie prebiehalo primárne pomocou nástroja Wireshark a referenčného servera. Okrem toho som využil súbory obsahujúce simulované vstupné príkazy, ktoré som presmeroval na vstup programu. Dodatočné testy boli vykonané pomocou vlastného Python skriptu. Tento prístup mi umožnil overiť správne fungovanie rôznych častí kódu a ich interakciu s klientmi v rôznych scenároch. Analyzovanie sieťovej komunikácie pomocou Wiresharku mi poskytlo podrobnejší pohľad na prenášané správy a ich formát, čo bolo kľúčové pre ladenie a zlepšenie spoľahlivosti serverovej aplikácie. Presmerovanie súboru na vstup mi umožnilo otestovať aj to, že program správne čaká na príchod odpovede od servera, ako je napríklad správa reply alebo confirm, a v tom čase nevykonáva ďalšie príkazy.

Udp Testy

Autentifikácia a zaslanie správy

Účel: Test overuje správne fungovanie autentifikácie na serveri a následné zaslanie správy po úspešnom prihlásení.

Akcie:

  1. Odoslanie autentifikačného požiadavku na server s použitím uvedeného používateľského mena a tajného kľúča.
  2. Odoslanie správy "hi" na server po úspešnom prihlásení.

Očakávané výsledky:

  1. Potvrdenie úspešnej autentifikácie serverom zaslaním reply OK a pripojenie uživateľa do predvoleného kánalu.
  2. Správa "hi" odoslaná na server a potvrdenie prijatia tejto správy serverom.

Vstup

/auth xpasti00 e8b8b8c4-a22f-40dd-b4c4-59c0781ac9b7 AP
hi

Výstup Wiresharku AUTH_MSG_UDP

Autentifikácia s nesprávnym tajným kľúčom

Účel: Overenie reakcie servera na autentifikačný požiadavok s nesprávnym tajným kľúčom a overenie inkrementácie id.

Akcie:

  1. Odoslanie autentifikačného požiadavku na server s použitím uvedeného používateľského mena a nesprávneho tajného kľúča.
  2. Opatovné odoslanie autentifikačného požiadavku s použitím uvedeného používateľského mena a správneho tajného kľúča.

Očakávané výsledky:

  1. Odpoveď servera reply NOK, keďže autentifikačné údaje sú nesprávne.
  2. Druhá autentifikačná správa potvrdená, zaslanie reply OK zo servera a pripojenie uživateľa do predvoleného kánalu.

Vstup

/auth xpasti00 badSecret AP
/auth xpasti00 e8b8b8c4-a22f-40dd-b4c4-59c0781ac9b7 AP

Výstup Wiresharku AUTH_NOK_OK_UDP

Premenovanie užívateľa

Účel: Overenie správnosti fungovania funkcie premenovania užívateľa na serveri.

Akcie:

  1. Odoslanie prvej správy s menom "AP"
  2. Zadanie príkazu na premenovanie
  3. Odoslanie druhej správy s novým menom "Adam"

Očakávané výsledky:

  1. Správa "hi" odoslaná s menom "AP" na server a potvrdenie servera o prijatí tejto správy.
  2. Druhá správa odoslaná s menom "Adam" na server a potvrdenie servera o prijatí tejto správy.

Vstup

/auth xpasti00 e8b8b8c4-a22f-40dd-b4c4-59c0781ac9b7 AP
hi
/rename Adam
i was renamed

Výstup Wiresharku RENAME_UDP

Zmena kanálu

Účel: Overenie správnosti fungovania funkcie zmeny kanálu.

Akcie:

  1. Zmena kanálu na "discord.verified-1"
  2. Odoslanie správy "hello from verified-1"

Očakávané výsledky:

  1. Potvrdenie požiadavku o pripojenie, odpoveď servera reply OK na zmenu kanálu a pripojenie uživateľa do nového kanálu.
  2. Správa "hello from verified-1" odoslaná do nového kanálu a potvrdená serverom.

Vstup

/auth xpasti00 e8b8b8c4-a22f-40dd-b4c4-59c0781ac9b7 AP
/join discord.verified-1
hello from verified-1

Výstup Wiresharku JOIN_MSG_UDP

Vypršanie času na prijatie správy

Účel: Tento test overuje správne fungovanie delayu na prijatie správy zo servera, keď je nastavený veľmi krátky časový limit.

Akcie:

  1. Spustenie programu s argumentom -d 1
  2. Pokus o zaslanie správy

Očakávané výsledky:

  1. Server nestihne do 1ms odoslať potvrdzujúcu správu a teda snaha o opätovné zaslanie správy.
  2. Po tom ako program trikrát nepríjme potvrdzujúcu spravú sa ukončí s chybou

Argumenty

-t udp -s anton5.fit.vutbr.cz -d 1

Vstup

/auth xpasti00 e8b8b8c4-a22f-40dd-b4c4-59c0781ac9b7 AP
hi

Výstup Wiresharku NO_RESPONSE_TCP

Prijatie chybovej správy

Tento test bol vykanný použitím vlastného Python skriptu, ktorý simuloval chybovú správu od servera

Účel: Test overuje správne fungovanie programu pri prijatí chybovej správy od servera.

Akcie:

  1. Simulácia odoslania chybovej správy od servera

Očakávané výsledky:

  1. Potvrdenie prijatia chybovej správy a odoslanie správy typu bye na server

Vstup

/auth xpasti00 123 AP

Výstup Wiresharku

RECEIVED_ERROR_UDP

Prijatie neznámej správy

Tento test bol vykanný použitím vlastného Python skriptu, ktorý simuloval neznámu správu od servera

Účel: Test overuje správne fungovanie programu pri prijatí neznámej správy od servera.

Akcie:

  1. Simulácia odoslania neznámej správy od servera

Očakávané výsledky:

  1. Potvrdenie prijatia neznámej správy
  2. Odoslanie správy typu err na server a ukončenie programu

Vstup

/auth xpasti00 123 AP

Výstup Wiresharku

UNKNOWN_MSG_UDP

Tcp Testy

Autentifikácia a zaslanie správy

Účel: Test overuje správne fungovanie autentifikácie na serveri a následné zaslanie správy po úspešnom prihlásení.

Akcie:

  1. Odoslanie autentifikačného požiadavku na server s použitím uvedeného používateľského mena a tajného kľúča.
  2. Odoslanie správy "hi" na server po úspešnom prihlásení.

Očakávané výsledky:

  1. Potvrdenie úspešnej autentifikácie zaslaním REPLY OK zo servera a pripojenie uživateľa do predvoleného kánalu.
  2. Správa "hi" odoslaná na server.

Vstup

/auth xpasti00 e8b8b8c4-a22f-40dd-b4c4-59c0781ac9b7 AP
hi

Výstup Wiresharku

AUTH_MSG_TCP

Autentifikácia s nesprávnym tajným kľúčom

Účel: Overenie reakcie servera na autentifikačný požiadavok s nesprávnym tajným kľúčom.

Akcie:

  1. Odoslanie autentifikačného požiadavku na server s použitím nesprávneho tajného kľúča.
  2. Opatovné odoslanie autentifikačného požiadavku s použitím správneho tajného kľúča.

Očakávané výsledky:

  1. Odoslanie REPLY NOK zo servera, keďže autentifikačné údaje sú nesprávne.
  2. Na druhú autentifikačnú správu odpoveď REPLY OK a pripojenie uživateľa do predvoleného kánalu.

Vstup

/auth xpasti00 badSecret AP
/auth xpasti00 e8b8b8c4-a22f-40dd-b4c4-59c0781ac9b7 AP

Výstup Wiresharku

AUTH_NOK_OK_TCP

Premenovanie užívateľa

Účel: Overenie správnosti fungovania funkcie premenovania užívateľa na serveri.

Akcie:

  1. Odoslanie prvej správy s menom "AP"
  2. Zadanie príkazu na premenovanie
  3. Odoslanie druhej správy s novým menom "Adam"

Očakávané výsledky:

  1. Správa "hi" odoslaná s menom "AP".
  2. Druhá správa odoslaná s novým menom "Adam".

Vstup

/auth xpasti00 e8b8b8c4-a22f-40dd-b4c4-59c0781ac9b7 AP
hi
/rename Adam
i was renamed

Výstup Wiresharku

RENAME_TCP

Zmena kanálu

Účel: Overenie správnosti fungovania funkcie zmeny kanálu.

Akcie:

  1. Zmena kanálu na "discord.verified-1"
  2. Odoslanie správy "hello from verified-1"

Očakávané výsledky:

  1. Odpoveď servera REPLY OK na zmenu kanálu a pripojenie uživateľa do nového kanálu.
  2. Správa "hello from verified-1" odoslaná do nového kanálu.

Vstup

/auth xpasti00 e8b8b8c4-a22f-40dd-b4c4-59c0781ac9b7 AP
/join discord.verified-1
hello from verified-1

Výstup Wiresharku

JOIN_MSG_UDP

Bibliografia

Licencia

LICENSE

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors