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 02:10]
Andrei Roșu-Cojocaru
laboratoare:laborator06 [2015/04/06 16:49] (current)
Andrei Roșu-Cojocaru
Line 8: Line 8:
  
 O mașină fizică și un dispozitiv fizic pot comunica: O mașină fizică și un dispozitiv fizic pot comunica:
-  - prin plasarea lor în aceeași rețea fără fir (WiFi), având adresele IP furnizate de un server DHCP ce se rulează pe un router;+  - prin plasarea lor în aceeași rețea fără fir (WiFi), având adresele IP furnizate de un server DHCP ce rulează pe un router;
   - prin stabilirea unei legături punct la punct, folosind Bluetooth;   - prin stabilirea unei legături punct la punct, folosind Bluetooth;
-  - printr-o conexiune ​pe portul ​USB.+  - printr-o conexiune ​de date realizată prin intermediul portului ​USB.
  
-TODO figura + configurare+Pe telefon, se accesează //​Settings//​ → //Wireless & Networks// → //Tethering & portable hotspot// și se selectează opțiunea //USB  Tethering//​ 
 + 
 +{{ :​laboratoare:​laborator06:​usb_tethering_configuration.png?​nolink&​400 }} 
 + 
 +Astfel, se va activa (în mod automat) interfața ''​rndis0'',​ pentru care se poate determina adresa Internet: 
 + 
 +<​code>​ 
 +student@pdsd2015:/​opt/​android-sdk-linux/​platform-tools$ ./adb devices 
 +List of devices attached 
 +0019531d59461f ​   device 
 +student@pdsd2015:/​opt/​android-sdk-linux/​platform-tools$ ./adb -s 0019531d59461f shell 
 +shell@n7000:/​ $ su 
 +su 
 +shell@n7000:/​ # ifconfig rndis0 
 +ifconfig rndis0 
 +rndis0: ip 192.168.42.129 mask 255.255.255.0 flags [up broadcast running multicast] 
 +shell@n7000:/​ # 
 +</​code>​ 
 + 
 +<note important>​Pe Linux, în situația în care dispozitivul mobil este detectat, fără a se indica tipul său, este necesar să se pornească serverul de ADB cu drepturi de administrator:​ 
 +<​code>​ 
 +student@pdsd2015:/​opt/​android-sdk-linux/​platform-tools$ ./adb devices 
 +List of devices attached 
 +0019531d59461f ​   ????????????​ 
 +student@pdsd2015:/​opt/​android-sdk-linux/​platform-tools$ sudo ./adb kill-server 
 +student@pdsd2015:/​opt/​android-sdk-linux/​platform-tools$ sudo ./adb start-server 
 +student@pdsd2015:/​opt/​android-sdk-linux/​platform-tools$ sudo ./adb devices 
 +List of devices attached 
 +0019531d59461f ​   device 
 +</​code>​ 
 + 
 +Pe Windows, dacă dispozitivul mobil nu este detectat, poate fi necesară instalarea unor drivere suplimentare pentru stabilirea legăturii prin intermediul portului USB. 
 +</​note>​ 
 + 
 +Ulterior, se determină adresa Internet a mașinii fizice, asociată interfeței ''​usb0''​ (Linux), respectiv Ethernet (Windows). 
 + 
 +<columns 100% 50%> 
 + 
 +**Linux** 
 + 
 +<​code>​ 
 +student@pdsd2015:​~$ sudo ifconfig usb0 
 +usb0      Link encap:​Ethernet ​ HWaddr 32:​ca:​4b:​1c:​ff:​7b  
 +          inet addr:​192.168.42.170 ​ Bcast:​192.168.42.255 ​ Mask:​255.255.255.0 
 +          inet6 addr: fe80::​30ca:​4bff:​fe1c:​ff7b/​64 Scope:​Link 
 +          UP BROADCAST RUNNING MULTICAST ​ MTU:​1500 ​ Metric:1 
 +          RX packets:109 errors:0 dropped:0 overruns:0 frame:0 
 +          TX packets:319 errors:0 dropped:0 overruns:0 carrier:0 
 +          collisions:​0 txqueuelen:​1000 
 +          RX bytes:24103 (23.5 KiB)  TX bytes:64369 (62.8 KiB) 
 +</​code>​ 
 + 
 +<​newcolumn>​ 
 + 
 +**Windows** 
 + 
 +<​code>​ 
 +C:\Program Files (x86)\Android\android-sdk\platform-tools>​ipconfig 
 + 
 +Windows IP Configuration 
 + 
 + 
 +Ethernet adapter Local Area Connection:​ 
 + 
 +   ​Connection-specific DNS Suffix ​ . : 
 +   ​Link-local IPv6 Address . . . . . : fe80::​18bf:​d0be:​3625:​6b1%44 
 +   IPv4 Address. . . . . . . . . . . : 192.168.42.81 
 +   ​Subnet Mask . . . . . . . . . . . : 255.255.255.0 
 +   ​Default Gateway . . . . . . . . . : 192.168.42.129 
 +</​code>​ 
 + 
 +</​columns>​
  
 ==== Dispozitiv Virtual (Emulator) ==== ==== Dispozitiv Virtual (Emulator) ====
Line 24: Line 95:
   * pentru dispozitivele virtuale sunt alocate adrese în intervalul ''​192.168.56.101''​ .. ''​192.168.56.254''​.   * pentru dispozitivele virtuale sunt alocate adrese în intervalul ''​192.168.56.101''​ .. ''​192.168.56.254''​.
  
-Configurarea spațiului de adrese care este folosit poate fi configurat prin intermediul VirtualBox.+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&​500 }}
  
-TODO figura+{{ :​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 36: Line 109:
   * prin intermediul plugin-ului Genymotion pentru mediul integrat de dezvoltare Eclipse Luna SR1a (4.4.1) - Ctrl + 6.   * prin intermediul plugin-ului Genymotion pentru mediul integrat de dezvoltare Eclipse Luna SR1a (4.4.1) - Ctrl + 6.
  
-TODO figura+{{ :​laboratoare:​laborator06:​genymotion_ip_addresses.png?​nolink&​700 }}
  
 Conectivitatea dintre mașina fizică și dispozitivul virtual poate fi verificată folosind comanda ''​ping''​. <​code>​ Conectivitatea dintre mașina fizică și dispozitivul virtual poate fi verificată folosind comanda ''​ping''​. <​code>​
Line 61: 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;
  
-TODO figura+{{ :​laboratoare:​laborator06:​android_virtual_device_port.png?​nolink&​600 }}
  
   * prin rularea comenzii ''​adb devices''​ <​code>​   * prin rularea comenzii ''​adb devices''​ <​code>​
Line 240: Line 313:
 Se dorește interogarea serverului National Institute of Standards & Technology, care oferă un serviciu de interogare a datei și orei curente, cu o precizie ridicată, conform [[https://​tools.ietf.org/​html/​rfc867|Daytime Protocol (RFC-867)]]. Se dorește interogarea serverului National Institute of Standards & Technology, care oferă un serviciu de interogare a datei și orei curente, cu o precizie ridicată, conform [[https://​tools.ietf.org/​html/​rfc867|Daytime Protocol (RFC-867)]].
  
-TODO figura+{{ :​laboratoare:​laborator06:​daytime_protocol.png?​nolink&​400 }}
  
 În acest sens, se va deschide un socket TCP, prin interogarea serverului disponibil la adresa [[time-b.nist.gov|]],​ pe portul 13, în cadrul unui fir de execuție separat (clasa ''​NISTCommunicationThread''​). Întrucât nu este necesară decât operația de primire a unor date, se va crea doar un obiect de tip ''​BufferedReader'',​ citindu-se două linii (una fiind vidă - așadar ignorată, cealaltă conținând informațiile necesare, care se doresc a fi afișate). Întrucât modificarea conținutului unui control grafic nu poate fi realizată decât din contextul firului de execuție în care a fost creat, acesta va fi obținut prin parametrul metodei ''​post()''​ a obiectului respectiv, doar aici fiind permisă asocierea conținutului solicitat. În momentul în care datele au fost preluate, socket-ul TCP poate fi închis. Pe fiecare eveniment de tip apăsare a butonului se va crea un fir de execuție dedicat în care se va instanția un obiect de tip ''​Socket''​. În acest sens, se va deschide un socket TCP, prin interogarea serverului disponibil la adresa [[time-b.nist.gov|]],​ pe portul 13, în cadrul unui fir de execuție separat (clasa ''​NISTCommunicationThread''​). Întrucât nu este necesară decât operația de primire a unor date, se va crea doar un obiect de tip ''​BufferedReader'',​ citindu-se două linii (una fiind vidă - așadar ignorată, cealaltă conținând informațiile necesare, care se doresc a fi afișate). Întrucât modificarea conținutului unui control grafic nu poate fi realizată decât din contextul firului de execuție în care a fost creat, acesta va fi obținut prin parametrul metodei ''​post()''​ a obiectului respectiv, doar aici fiind permisă asocierea conținutului solicitat. În momentul în care datele au fost preluate, socket-ul TCP poate fi închis. Pe fiecare eveniment de tip apăsare a butonului se va crea un fir de execuție dedicat în care se va instanția un obiect de tip ''​Socket''​.
Line 427: 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 469: Line 550:
 } }
 </​file>​ </​file>​
 +
 +{{ :​laboratoare:​laborator06:​single_threaded_server.png?​nolink&​400 }}
 +
 +Prin intermediul utilitarului ''​nc''​ (apelat cu adresa Internet și portul serverului) se poate interoga mesajul care a fost transmis. De asemenea, comanda ''​time''​ măsoară timpul în care a fost executată operația respectivă.
 +
 +<​code>​
 +student@pdsd2015:​~$ nc 192.168.56.101 2015
 +Hello, PDSD Student!
 +student@pdsd2015:​~$ time nc 192.168.56.101 2015
 +Hello, PDSD Student!
 +
 +real    0m0.009s
 +user    0m0.000s
 +sys     ​0m0.000s
 +</​code>​
  
 Fiecare comunicație dintre client și server este tratată secvențial,​ ceea ce poate determina latențe semnificative în cazul în care sunt înregistrate mai multe solicitări de acest tip concomitent. ​ Fiecare comunicație dintre client și server este tratată secvențial,​ ceea ce poate determina latențe semnificative în cazul în care sunt înregistrate mai multe solicitări de acest tip concomitent. ​
Line 521: Line 617:
   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 567: Line 671:
 </​code>​ </​code>​
  
 +**4.** Să se importe în mediul integrat de dezvoltare Eclipse Luna SR1a (4.4.1) proiectul ''​01-FTPServerWelcomeMessage''​ din directorul ''​labtasks''​.
 +
 +Se cere să se implementeze o aplicație Android care citește mesajul de întâmpinare transmis în momentul în care se realizează o conexiune către un server FTP. 
 +
 +Adresa Internet a serverului FTP la care se dorește să se realizeze conexiunea va fi introdusă de utilizator, iar portul curent este 21 (reținut în ''​Constants.FTP_PORT''​).
 +
 +În cazul în care mesajul de întâmpinare conține mai multe linii, mesajul este precedat de șirul de caractere ''​220-''​ (reținut în ''​Constants.FTP_MULTILINE_START_CODE''​). Mesajul se încheie fie cu șirul de caractere ''​220'',​ fie cu un șir de caractere precedat de ''​220 ''​ (valori stocate în ''​Constants.FTP_MULTILINE_END_CODE1'',​ respectiv ''​Constants.FTP_MULTILINE_END_CODE2''​).
 +
 +{{ :​laboratoare:​laborator06:​ftp_server_welcome_message.png?​nolink&​400 }}
 +
 +Operațiile care trebuie realizate pe metoda ''​run()''​ a firului de execuție ce gestionează comunicația cu serverul FTP sunt:
 +  - deschiderea unui socket care primește ca parametrii:
 +    - adresa Internet a serverului FTP (precizată anterior de utilizator, preluată din câmpul text ''​FTPServerAddressEditText''​)
 +    - portul 21 (preluat din ''​Constants.FTP_PORT''​).
 +  - obținerea fluxului de intrare atașat socket-ului,​ printr-un apel al metodei ''​Utilities.getBufferedReader()'';​
 +  - citirea unei linii de pe fluxul de intrare:
 +    - dacă aceasta începe cu șirul de caractere ''​220-''​ (preluat din ''​Constants.FTP_MULTILINE_START_CODE''​),​ mesajul este analizat;
 +      - se citesc linii de pe fluxul de intrare atașat socket-ului cât timp valoarea:
 +        - nu este egală cu ''​220''​ (preluat din ''​Constants.FTP_MULTILINE_END_CODE1''​);​
 +        - nu începe cu ''​220 ''​ (preluat din ''​Constants.FTP_MULTILINE_END_CODE2''​);​
 +      - valoarea primită de la serverul FTP este inclusă în câmpul text ''​welcomeMEssageTextView'';​
 +    - altfel, mesajul este ignorat.
 +  - închiderea socket-ului.
 +
 +Să se verifice mesajul afișat în momentul în care se realizează o conexiune la serverul ''​ftp.ngc.com''​.
 +
 +**5.** Să se importe în mediul integrat de dezvoltare Eclipse Luna SR1a (4.4.1) proiectul ''​02-SingleThreadedServer''​ din directorul ''​labtasks''​.
 +
 +Acesta reprezintă o aplicație Android care implementează un server ce ascultă pe un port (2015, în ''​Constants.SERVER_PORT''​) solicitări de conexiune provenite de la clienți.
 +
 +Pe același fir de execuție pe care se face așteptarea,​ este realizată și transmiterea mesajului către client, preluat dintr-un câmp text.
 +
 +Pornirea serverului se face prin introducerea în câmpul text a șirului de caractere ''​Start Server''​.
 +
 +Oprirea serverului se face prin introducerea în câmpul text a șirului de caractere ''​Stop Server''​.
 +
 +Preluarea invocărilor de la clienți este realizată doar atâta timp cât serverul se află în execuție.
 +
 +===
 +
 +**Linux**
 +
 +Citirea mesajelor se face cu ''​nc''​ care primește ca parametrii adresa Internet și portul serverului de pe dispozitivul Android. Prin utilitarul ''​time''​ se verifică durata operației respective.
 +
 +<​code>​
 +student@pdsd2015:​~$ nc 192.168.56.101 2015
 +Hello, PDSD Student!
 +student@pdsd2015:​~$ time nc 192.168.56.101 2015
 +Hello, PDSD Student!
 +
 +real    0m0.009s
 +user    0m0.000s
 +sys     ​0m0.000s
 +</​code>​
 +
 +**Windows**
 +
 +Citirea mesajelor se face cu ''​telnet''​ care primește ca parametrii adresa Internet și portul serverului de pe dispozitivul Android.
 +
 +Î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&​300 }}
 +
 +{{ :​laboratoare:​laborator06:​telnet02_windows81.png?​nolink&​600 }}
 +
 +{{ :​laboratoare:​laborator06:​telnet03_windows81.png?​nolink }}
 +
 +{{ :​laboratoare:​laborator06:​telnet04_windows81.png?​nolink&​400 }}
 +
 +{{ :​laboratoare:​laborator06:​telnet05_windows81.png?​nolink&​400 }}
 +
 +<​code>​
 +C:​\Users\Student>​ telnet 192.168.56.101 2015
 +Start Server
 +
 +Connection to host lost.
 +C:​\Users\Student>​ telnet 192.168.56.101 2015
 +Connecting To 192.168.56.101...Could not open connection to the host, on port 2015: Connect failed
 +</​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''​.
  
-**???.**  Să se încarce modificările realizate în cadrul depozitului '​Laborator06'​ de pe contul Github personal, folosind un mesaj sugestiv. <​code>​+**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.1428275432.txt.gz · Last modified: 2015/04/06 02:10 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