Gestiunea unei Conexiuni către Servicii Disponibile
Fiecare dispozitiv poate fi avea în același timp rolul de:
- server pentru serviciile pe care le-a înregistrat, putând primi solicitări din partea clienților;
- client pentru serviciile pe care le-a descoperit, putând trimite solicitări către servere.
În acest sens, va trebui menținut un obiect server, care va gestiona comunicația cu clienții.
Totodată, vor trebui menținuți mai mulți clienți, reprezentând canalele de comunicație de tip punct-la-punct care pot fi de două tipuri:
- canale de comunicație pentru solicitări primite (clienți);
- canale de comunicație pentru servicii descoperite (servere).
public class NetworkServiceDiscoveryOperations {
private ChatServer chatServer = null;
private List<ChatClient> communicationToServers = null;
private List<ChatClient> communicationFromClients = null;
* ...
}
Actualizarea acestor obiecte va fi realizată mai ales în situația în care un serviciu este rezolvat, respectiv un serviciu este pierdut.
Obiectul de tip ChatServer
este de fapt un fir de execuție pe care
se instanțiază un obiect de tip ServerSocket
, așteptându-se, în bucla
principală, solicitări de la clienți, actualizându-se corespunzător
lista conținând canalele de comunicație pentru solicitările primite.
De remarcat faptul că a fost definită și o metodă pentru oprirea firului
de execuție și închiderea obiectului ServerSocket
, aceasta urmând a fi
apelată la deînregistrarea serviciului respectiv.
public class ChatServer extends Thread {
private NetworkServiceDiscoveryOperations networkServiceDiscoveryOperations = null;
private ServerSocket serverSocket = null;
public ChatServer(NetworkServiceDiscoveryOperations networkServiceDiscoveryOperations, int port) {
this.networkServiceDiscoveryOperations = networkServiceDiscoveryOperations;
try {
serverSocket = new ServerSocket(port);
} catch (IOException ioException) {
Log.e(Constants.TAG, "An error has occurred during server run: " + ioException.getMessage());
if (Constants.DEBUG) {
ioException.printStackTrace();
}
}
}
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
Socket socket = serverSocket.accept();
List<ChatClient> communicationFromClients = networkServiceDiscoveryOperations.getCommunicationFromClients();
communicationFromClients.add(new ChatClient(null, socket));
networkServiceDiscoveryOperations.setCommunicationFromClients(communicationFromClients);
}
} catch (IOException ioException) {
Log.e(Constants.TAG, "An error has occurred during server run: " + ioException.getMessage());
if (Constants.DEBUG) {
ioException.printStackTrace();
}
}
}
public void stopThread() {
interrupt();
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (IOException ioException) {
Log.e(Constants.TAG, "An error has occurred while closing server socket: " + ioException.getMessage());
if (Constants.DEBUG) {
ioException.printStackTrace();
}
}
}
}
Obiectul de tip ChatClient
definește un canal de comunicație
bidirecțional între două mașini / dispozitive, care poate fi creat pe
baza unei adrese și a unui port (conexiune către server) sau pe baza
altui canal de comunicație (conexiune de la client).
Acesta încapsulează două fire de execuție:
SendThread
- pentru trimiterea de mesaje;ReceiveThread
- pentru primirea de mesaje.
Atât mesajele trimise cât și mesajele trimise sunt plasate și în interfața grafică (dacă aceasta este vizibilă) dar și într-un obiect membru al clasei.
Au fost definite metode atât pentru pornirea cât și pentru oprirea firelor de execuție. Astfel, firele de execuție pentru trimiterea / primirea de mesaje rulează cât timp nu sunt întrerupte.
public class ChatClient {
private Socket socket = null;
private SendThread sendThread = null;
private ReceiveThread receiveThread = null;
private BlockingQueue<String> messageQueue = new ArrayBlockingQueue<String>(Constants.MESSAGE_QUEUE_CAPACITY);
private List<Message> conversationHistory = new ArrayList<Message>();
public ChatClient(final String host, final int port) {
try {
socket = new Socket(host, port);
} catch (IOException ioException) {
Log.e(Constants.TAG, "An exception has occurred while creating the socket: " + ioException.getMessage());
if (Constants.DEBUG) {
ioException.printStackTrace();
}
}
if (socket != null) {
startThreads();
}
}
public ChatClient(Context context, Socket socket) {
this.socket = socket;
if (socket != null) {
startThreads();
}
}
public void sendMessage(String message) {
try {
messageQueue.put(message);
} catch (InterruptedException interruptedException) {
Log.e(Constants.TAG, "An exception has occurred: " + interruptedException.getMessage());
if (Constants.DEBUG) {
interruptedException.printStackTrace();
}
}
}
private class SendThread extends Thread {
@Override
public void run() {
PrintWriter printWriter = Utilities.getWriter(socket);
if (printWriter != null) {
try {
while (!Thread.currentThread().isInterrupted()) {
String content = messageQueue.take();
if (content != null) {
printWriter.println(content);
printWriter.flush();
Message message = new Message(content, Constants.MESSAGE_TYPE_SENT);
conversationHistory.add(message);
* display the message in the graphic user interface
}
}
} catch (InterruptedException interruptedException) {
Log.e(Constants.TAG, "An exception has occurred: " + interruptedException.getMessage());
if (Constants.DEBUG) {
interruptedException.printStackTrace();
}
}
}
}
public void stopThread() {
interrupt();
}
}
private class ReceiveThread extends Thread {
@Override
public void run() {
BufferedReader bufferedReader = Utilities.getReader(socket);
if (bufferedReader != null) {
try {
while (!Thread.currentThread().isInterrupted()) {
String content = bufferedReader.readLine();
if (content != null) {
Message message = new Message(content, Constants.MESSAGE_TYPE_RECEIVED);
conversationHistory.add(message);
* display the message in the graphic user interface
}
}
} catch (IOException ioException) {
Log.e(Constants.TAG, "An exception has occurred: " + ioException.getMessage());
if (Constants.DEBUG) {
ioException.printStackTrace();
}
}
}
}
public void stopThread() {
interrupt();
}
}
public void setConversationHistory(List<Message> conversationHistory) {
this.conversationHistory = conversationHistory;
}
public List<Message> getConversationHistory() {
return conversationHistory;
}
public void startThreads() {
sendThread = new SendThread();
sendThread.start();
receiveThread = new ReceiveThread();
receiveThread.start();
}
public void stopThreads() {
sendThread.stopThread();
receiveThread.stopThread();
try {
if (socket != null) {
socket.close();
}
} catch (IOException ioException) {
Log.e(Constants.TAG, "An exception has occurred while closing the socket: " + ioException.getMessage());
if (Constants.DEBUG) {
ioException.printStackTrace();
}
}
}
}