Clientul
Conexiunea unui client la un server se poate realiza numai în situația în care
sunt cunoscute adresa IP (sau denumirea, rezolvată apoi prin intermediul DNS)
și portul la care acesta așteaptă să fie invocat. Aceste valori sunt transmise
ca parametrii în constructorul obiectului Socket
. Ulterior, operațiile de
comunicație (citire / scriere) sunt realizate prin operații pe fluxuri de
intrare (InputStream
) și pe fluxuri de ieșire (OutputStream
).
Așadar, comunicația prin intermediul unui obiect de tip Socket
presupune
următorii pași:
1. deschiderea unui socket, prin transmiterea parametrilor de
identificare a gazdei (adresă IP / denumire și port) ca parametrii ai
constructorului unui obiect de tip Socket
String hostname = "localhost";
int port = 2000;
Socket socket = new Socket(hostname, port);
2. crearea unui output stream pentru a trimite date prin intermediul socket-ului TCP și trimiterea efectivă a datelor:
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
PrintWriter printWriter = new PrintWriter(bufferedOutputStrea, true);
De remarcat faptul că obiectul
PrintWriter
primește în constructor un parametru de tipboolean
prin care se indică dacă transmiterea efectivă a datelor este realizată sau nu în mod automat atunci când se întâlnește caracterul\n
(newline).
Metodele implementate de clasa
PrintWriter
sunt similare cu cele oferite de PrintStream
(clasa folosită de
metodele din System.out
), diferența fiind faptul că pot fi create mai
multe instanțe pentru seturi de caractere Unicode diferite:
Trimiterea efectivă a datelor este realizată atunci când se apelează metoda flush() sau automat la întâlnirea caracterului '\n', în funcție de argumentele cu care a fost invocat constructorul.
3. crearea unui flux de intrare pentru a primi date prin intermediul socket-ului TCP și primirea efectivă a datelor:
InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
Metodele implementate de clasa BufferedReader sunt:
- read() - pentru a primi un singur caracter (dacă este apelată fără parametrii) sau un tablou de caractere (de o anumită dimensiune, acestea fiind stocate într-un vector furnizat ca parametru, începând cu o anumită poziție);
- readLine() - pentru a primi o linie.
Metoda
readLine()
este blocantă, așteptând un mesaj terminat prin\n
(newline). În situația în care conexiunea este terminată, se transmiteEOF
, iar metoda întoarce valoareanull
.
Note
Pot fi utilizate obiecte de tipul ObjectOutputStream
și
ObjectInputStream
pentru transmiterea de obiecte Java, atunci când
entitățile care comunică rulează în contextul unei mașini virtuale de
acest tip (JVM).
Se recomandă ca obținerea de referințe către fluxul de intrare respectiv
fluxul de ieșire asociate unui obiect de tip Socket
să fie realizată
prin intermediul unor metode statice definite în cadrul unor clase
ajutător:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Utilities {
public static BufferedReader getReader(Socket socket) throws IOException {
return new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
public static PrintWriter getWriter(Socket socket) throws IOException {
return new PrintWriter(socket.getOutputStream(), true);
}
}
4. închiderea obiectului Socket
, atunci când acesta nu mai este
necesar
socket.close();
În momentul în care se apelează metoda close()
, sunt transmise și
datele care erau stocate în zonele de memorie tampon.