Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
laboratoare:laborator06 [2015/04/06 13:36]
Andrei Roșu-Cojocaru
laboratoare:laborator06 [2015/04/06 16:49] (current)
Andrei Roșu-Cojocaru
Line 97: Line 97:
 Configurarea spațiului de adrese care este folosit poate fi configurat prin intermediul VirtualBox, accesând //File// → //​Preferences//​ → //Network// → //Host Only Networks// Configurarea spațiului de adrese care este folosit poate fi configurat prin intermediul VirtualBox, accesând //File// → //​Preferences//​ → //Network// → //Host Only Networks//
  
-{{ :​laboratoare:​laborator06:​virtualbox01.png?​nolink&​600 }}+{{ :​laboratoare:​laborator06:​virtualbox01.png?​nolink&​500 }}
  
-{{ :​laboratoare:​laborator06:​virtualbox02.png?​nolink&​600 }}+{{ :​laboratoare:​laborator06:​virtualbox02.png?​nolink&​500 }}
  
 Adresa IP care a fost atașată fiecărui dispozitiv virtual Genymotion poate fi verificată:​ Adresa IP care a fost atașată fiecărui dispozitiv virtual Genymotion poate fi verificată:​
Line 134: Line 134:
   * prin inspectarea ferestrei în care este afișat emulatorul, având forma //Android Emulator (55nr)//, unde nr poate lua valori cuprinse între 54 și 87 (doar valori impare - pentru portul de consolă, valorile pare fiind rezervate pentru portul adb); astfel, sunt suportate maxim 16 instanțe de dispozitive virtuale Android simultan;   * prin inspectarea ferestrei în care este afișat emulatorul, având forma //Android Emulator (55nr)//, unde nr poate lua valori cuprinse între 54 și 87 (doar valori impare - pentru portul de consolă, valorile pare fiind rezervate pentru portul adb); astfel, sunt suportate maxim 16 instanțe de dispozitive virtuale Android simultan;
  
-{{ :​laboratoare:​laborator06:​android_virtual_device_port.png?​nolink&​400 }}+{{ :​laboratoare:​laborator06:​android_virtual_device_port.png?​nolink&​600 }}
  
   * prin rularea comenzii ''​adb devices''​ <​code>​   * prin rularea comenzii ''​adb devices''​ <​code>​
Line 500: Line 500:
     public void stopServer() {     public void stopServer() {
       isRunning = false;       isRunning = false;
-      ​try { +      ​new Thread(new Runnable() ​{ 
-        serverSocket.close();​ +        ​@Override 
-      } catch(IOException ioException) { +        public void run() { 
-        Log.e(Constants.TAG,​ "An exception has occurred: "​+ioException.getMessage());​ +          try { 
-        if (Constants.DEBUG) { +            if (serverSocket != null) { 
-          ioException.printStackTrace();​+              ​serverSocket.close();​ 
 +            } 
 +            Log.v(Constants.TAG,​ "​stopServer() method invoked "​+serverSocket);​ 
 +          ​} catch(IOException ioException) { 
 +            Log.e(Constants.TAG,​ "An exception has occurred: "​+ioException.getMessage());​ 
 +            if (Constants.DEBUG) { 
 +              ioException.printStackTrace();​ 
 +            } 
 +          }
         }         }
-      }+      }).start();
     }     }
     ​     ​
Line 724: Line 732:
 În situația în care Telnet nu este disponibil, se accesează //Control Panel// → //Programs and Features// → //Turn Windows Features on or off//, selectându-se produsul //Telnet Client//. În situația în care Telnet nu este disponibil, se accesează //Control Panel// → //Programs and Features// → //Turn Windows Features on or off//, selectându-se produsul //Telnet Client//.
  
-{{ :​laboratoare:​laborator06:​telnet01_windows81.png?​nolink&​400 }}+{{ :​laboratoare:​laborator06:​telnet01_windows81.png?​nolink&​300 }}
  
-{{ :​laboratoare:​laborator06:​telnet02_windows81.png?​nolink&​400 }}+{{ :​laboratoare:​laborator06:​telnet02_windows81.png?​nolink&​600 }}
  
-{{ :​laboratoare:​laborator06:​telnet03_windows81.png?​nolink&​400 ​}}+{{ :​laboratoare:​laborator06:​telnet03_windows81.png?​nolink }}
  
 {{ :​laboratoare:​laborator06:​telnet04_windows81.png?​nolink&​400 }} {{ :​laboratoare:​laborator06:​telnet04_windows81.png?​nolink&​400 }}
Line 745: Line 753:
 === ===
  
-**???​.** ​ Să se încarce modificările realizate în cadrul depozitului '​Laborator06'​ de pe contul Github personal, folosind un mesaj sugestiv. <​code>​+**a)** Să se trimită aplicația Android în fundal prin apăsarea tastei //Home//. Verificați conectivitatea cu serverul. De ce sunt tratate cererile în continuare? 
 + 
 +**b)** Să se apese tasta //Back//. De ce sunt tratate cererile în continuare după ce aplicația Android este distrusă? Ce se întâmplă în momentul în care se dorește să se repornească aplicația Android? Cum ar putea fi remediată această problemă?​ 
 + 
 +Aplicația Android este distrusă, însă resursele utilizate de acestea nu sunt eliberate, motiv pentru care serverul continuă să gestioneze solicitările primite de la clienți. 
 + 
 +Astfel, în momentul în care se dorește să se repornească aplicația Android, se va genera o excepție, întrucât portul pe care se dorește să asculte serverul invocările de la clienți este deja ocupat. 
 + 
 +<​code>​ 
 +04-06 00:​00:​00.000:​ E/Single Threaded Server(934):​ An exception has occurred: bind failed: EADDRINUSE (Address already in use) 
 +04-06 00:​00:​00.000:​ W/​System.err(934):​ java.net.BindException:​ bind failed: EADDRINUSE (Address already in use) 
 +04-06 00:​00:​00.000:​ W/​System.err(934): ​    at libcore.io.IoBridge.bind(IoBridge.java:​89) 
 +04-06 00:​00:​00.000:​ W/​System.err(934): ​    at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:​150) 
 +04-06 00:​00:​00.000:​ W/​System.err(934): ​    at java.net.ServerSocket.<​init>​(ServerSocket.java:​100) 
 +04-06 00:​00:​00.000:​ W/​System.err(934): ​    at java.net.ServerSocket.<​init>​(ServerSocket.java:​69) 
 +</​code>​ 
 + 
 +O soluție ar putea fi eliberarea resurselor pe metoda ''​onDestroy()''​. 
 + 
 +<code java> 
 +@Override 
 +public void onDestroy() { 
 +  super.onDestroy();​ 
 +  serverThread.stopServer();​ 
 +} 
 +</​code>​ 
 + 
 +**c)** Să se simuleze faptul că operația de comunicare dintre client și server durează o perioadă de timp mai mare (spre exemplu, 3 secunde). Ce se întâmplă în momentul în care există mai multe solicitări trimise simultan de mai mulți clienți (din console diferite)? Monitorizați timpul de răspuns în această situație. 
 + 
 +Metoda ''​Thread.sleep()'',​ primind ca parametru un interval de timp (exprimat în milisecunde) simulează o așteptare, după care execuția aplicației Android este reluată în mod normal. 
 + 
 +<code java> 
 +try { 
 +  Thread.sleep(3000);​ 
 +} catch (InterruptedException interruptedException) { 
 +  Log.e(Constants.TAG,​ interruptedException.getMessage());​ 
 +  if (Constants.DEBUG) { 
 +    interruptedException.printStackTrace();​ 
 +  } 
 +} 
 +</​code>​ 
 + 
 +**d)** Să se implementeze comunicația pentru fiecare conexiune dintre client și server pe un fir de execuție separat, astfel încât pe server, gestiunea solicitărilor provenite de la clienți să nu fie afectată. 
 + 
 +**6.** Să se importe în mediul integrat de dezvoltare Eclipse Luna SR1a (4.4.1) proiectul ''​03-ClientServerCommunication''​ din directorul ''​labtasks''​. 
 + 
 +Acesta reprezintă o aplicație Android având două fragmente, implementând atât un server cât și un client: 
 +  - serverul dispune de un câmp text prin intermediul căruia: 
 +    - pot fi realizate diferite operații asupra sa: 
 +      - pornire, prin introducerea mesajului //Start Server//; 
 +      - oprire, prin introducerea mesajului //Stop Server//. 
 +    - se poate preciza un mesaj care să fie transmis către client prin intermediul canalului de comunicație;​ 
 +  - clientul dispune de două câmpuri text, prin care se precizează parametrii de conexiune la server (adresa de Internet / portul) precum și un buton prin intermediul căruia se realizează legătura propriu-zisă,​ fiind preluată informația din cadrul canalului de comunicație și afișată corespunzător. 
 + 
 +{{ :​laboratoare:​laborator06:​client_server_communication01.png?​nolink&​400 }} 
 + 
 +**a)** Să se implementeze funcționalitatea serverului. 
 + 
 +În clasa ''​ComunicationThread''​ din fragmentul asociat serverului:​ 
 +  - se obține o referință către fluxul de ieșire asociat socket-ului,​ prin intermediul metodei ajutătoare ''​Utilities.getWriter()'';​ 
 +  - se scrie o linie conținând textul din ''​serverTextEditText''​. 
 + 
 +**b)** Să se implementeze funcționalitatea clientului. 
 + 
 +În clasa ''​ClientThread''​ din fragmentul asociat serverului:​ 
 +  - se resetează conținutul câmpului text ''​serverMessageTextView'',​ astfel încât acesta să conțină șirul vid; 
 +  - se obțin parametrii de conexiune la server (adresa de Internet, obținută din câmpul text ''​serverAddressEditText''​ și portul, obținut din câmpul text ''​serverPortEditText''​);​ 
 +  - se deschide un socket, folosind configurația precizată de utilizator;​ 
 +  - se obține o referință către fluxul de intrare asociat socket-ului,​ prin intermediul metodei ajutătoare ''​Utilities.getReader()'';​ 
 +  - se citesc linii din contextul canalului de comunicație,​ atâta timp cât nu se întâlnește ''​EOF''​ (nu se întoarce valoarea ''​null''​),​ valoarea fiind concatenată la câmpul text ''​serverMessageTextView'';​ 
 +  - se închide socketul. 
 + 
 +<note important>​Accesul la controalele grafice trebuie să fie realizat numai din contextul firului de execuție asociat interfeței cu utilizatorul.</​note>​ 
 + 
 +**c)** Să se pornească serverul (se introduce textul //Start Server//). În client, să se verifice valoarea furnizată în cazul în care se introduc valorile ''​127.0.0.1''​ / ''​2015'',​ respectiv ''​localhost''​ / ''​2015''​.  
 + 
 +Să se oprească serverul (se introduce textul //Stop Server//). Să se verifice ce valori sunt furnizate în această situație. 
 + 
 +**d)** (doar Linux) Să se creeze o listă cu procesele care rulează la momentul curent, textul putând fi obținut, linie cu linie, prin intermediul unei conexiuni pe portul 2015, serverul fiind astfel simulat pe mașina fizică. 
 + 
 +<​code>​ 
 +student@pdsd2015:​~$ ps a | while read x; do echo "​$x"​ | nc -l 2015; done 
 +</​code>​ 
 + 
 +Să se folosească clientul pentru a citi, linie cu linie, valorile furnizate de script-ul anterior. Va trebui precizată adresa mașinii fizice (în funcție de configurația folosită) și portul 2015. 
 + 
 +{{ :​laboratoare:​laborator06:​client_server_communication02.png?​nolink&​400 }} 
 + 
 +**7.** Să se importe în mediul integrat de dezvoltare Eclipse Luna SR1a (4.4.1) proiectul ''​04-PheasantGame''​ din directorul ''​labtasks''​. 
 + 
 +Acesta reprezintă o aplicație Android care implementează jocul Fazan în limba engleză, atât partea de server, cât și partea de client. 
 + 
 +Vor fi folosite următoarele **reguli de joc**: 
 +  - clientul trimite un cuvânt serverului;​ 
 +  - serverul verifică dacă nu s-a solicitat terminarea jocului, situație în care continuă analiza termenului respectiv;​ 
 +  - dacă s-a primit un cuvânt care are prefixul așteptat, termenul existând în limba engleză, se caută un alt cuvânt care începe cu ultimele 2 litere ale termenului:​ 
 +    - dacă există un astfel de cuvânt, acesta fiind transmis înapoi clientului;​ 
 +    - altfel, se semnalează faptul că jocul s-a terminat; 
 +  - altfel, se trimite înapoi cuvântul primit pentru a semnala faptul că există o problemă. 
 + 
 +{{ :​laboratoare:​laborator06:​pheasant_game.png?​nolink&​400 }} 
 + 
 +Astfel, serverul va avea următoarea funcționare:​ 
 +  - dacă se primește //End Game// (stocat în ''​Constants.END_GAME''​),​ pentru a se indica faptul că nu se mai dorește continuarea jocului sau clientul a fost închis (nu găsește nici un cuvânt cu prefixul solicitat), serverul își termină execuția;​ 
 +  - altfel, serverul verifică dacă termenul care a fost primit reprezintă un cuvânt valid în limba engleză (accesând în acest sens pagina Internet [[http://​www.wordhippo.com/​what-is/​words-starting-with/​|]]) - se folosește metoda ''​Utilities.wordValidation()'';​ 
 +    - dacă termenul este valid: 
 +      - verifică dacă termenul începe cu prefixul solicitat (ultimele 2 litere ale cuvântului pe care l-a trimis anterior) - în acest sens, trebuie reținut cel mai recent cuvânt transmis / prefixul așteptat;​ 
 +        - în caz afirmativ:​ 
 +          - identifică prefixul cuvântului pe care trebuie să îl formeze (ultimele 2 litere ale cuvântului primit); 
 +          - realizează o interogare la nivelul paginii Internet [[http://​www.wordhippo.com/​what-is/​words-starting-with/​|]] pentru a obține lista cuvintelor care respectă constrângerea respectivă - se folosește metoda ''​Utilities.getWordListStartingWith()''​ care furnizează un obiect ''​List<​String>'';​ 
 +            - dacă lista conține unul sau mai multe cuvinte, face o alegere întâmplătoare și se transmite clientului;​ 
 +            - dacă lista nu conține nici un cuvânt, transmite clientului șirul de caractere //End Game// (stocat în ''​Constants.END_GAME''​),​ pentru a indica faptul că a fost închis (nu găsește nici un cuvânt cu prefixul solicitat);​ 
 +        - în caz negativ, transmite înapoi cuvântul pe care l-a primit; 
 +    - dacă termenul nu este valid, trimite înapoi cuvântul pe care l-a primit. 
 + 
 +<note important>​Este posibil ca un cuvânt care există în limba engleză să nu fie marcat ca valid, datorită faptului că se inspectează numai prima pagină dintre cele care conțin lista de cuvinte precedate de un anumit prefix.</​note>​ 
 + 
 +Similar, clientul va avea următoarea funcționare:​ 
 +  - dacă termenul din câmpul text ''​wordEditText''​ are mai mult de două caractere, este trimis clientului;​ 
 +  - se primește o valoare de la server: 
 +    - dacă se primește //End Game//, se invalidează controalele grafice, astfel încât jocul să nu poată fi continuat;​ 
 +    - dacă s-a primit alt cuvânt decât cel trimis anterior, se determină prefixul cu care trebuie format termenul și se afișează în câmpul text ''​wordEditText'';​ 
 +    - dacă s-a primit același cuvânt cu cel trimis anterior, înseamnă că termenul nu a fost corect, astfel încât trebuie format un cuvânt cu același prefix ca anterior, acesta fiind afișat în câmpul text ''​wordEdiTtext'';​ 
 +  - altfel, se afișează un mesaj de eroare. 
 + 
 +Informațiile cu privire la șirurile de caractere care au fost trimise, respectiv primite, vor fi jurnalizate în câmpurile text ''​serverHistoryTextView''​ și ''​clientHistoryTextView''​. 
 + 
 +**8.**  Să se încarce modificările realizate în cadrul depozitului '​Laborator06'​ de pe contul Github personal, folosind un mesaj sugestiv. <​code>​
 student@pdsd2015:​~/​Laborator06$ git add * student@pdsd2015:​~/​Laborator06$ git add *
 student@pdsd2015:​~/​Laborator06$ git commit -m "​implemented taks for laboratory 06" student@pdsd2015:​~/​Laborator06$ git commit -m "​implemented taks for laboratory 06"
laboratoare/laborator06.1428316577.txt.gz · Last modified: 2015/04/06 13:36 by Andrei Roșu-Cojocaru
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0