Fórum Socket UDP + Java + Rede Anel #586676
11/10/2017
0
Boa noite,
Estou com um problemão: Tenho um trabalho para entregar, basicamente tenho que criar um Chat UDP que rode em uma Rede Anel, ou seja, quando a aplicação recebe o token envia uma mensagem que estava em fila segurando a thread e só liberando o recurso quando receber o ACK confirmando a entrega do pacote. Tenho que usar uma estrutura pré-definida pelo professor, e isso acabou mais atrapalhando que ajudando. Então preciso de ajuda, não estou conseguindo fazer funcionar o chat.
Segue o código, qualquer ajuda é infinitamente bem vinda.
Controlador de mensagens
Gerenciador de fila de mensagem
Estou com um problemão: Tenho um trabalho para entregar, basicamente tenho que criar um Chat UDP que rode em uma Rede Anel, ou seja, quando a aplicação recebe o token envia uma mensagem que estava em fila segurando a thread e só liberando o recurso quando receber o ACK confirmando a entrega do pacote. Tenho que usar uma estrutura pré-definida pelo professor, e isso acabou mais atrapalhando que ajudando. Então preciso de ajuda, não estou conseguindo fazer funcionar o chat.
Segue o código, qualquer ajuda é infinitamente bem vinda.
Controlador de mensagens
package TokenRing;
import java.io.IOException;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.*;
public class MessageController implements Runnable {
private MessageQueue queue;
/*Tabela de roteamento */
private InetAddress IPAddress;
private int port;
private Semaphore WaitForMessage;
private String nickname;
private int time_token;
private Boolean token;
public MessageController(MessageQueue q,
String ip_port,
int t_token,
Boolean t,
String n) throws UnknownHostException {
queue = q;
String aux[] = ip_port.split(":");
IPAddress = InetAddress.getByName(aux[0]);
port = Integer.parseInt(aux[1]);
time_token = t_token;
token = t;
nickname = n;
WaitForMessage = new Semaphore(0);
}
/**
* ReceiveMessage() Nesta função, vc deve decidir o que fazer com a mensagem
* recebida do vizinho da esquerda: Se for um token, é a sua chance de
* enviar uma mensagem de sua fila (queue); Se for uma mensagem de dados e
* se for para esta estação, apenas a exiba no console, senão, envie para
* seu vizinho da direita; Se for um ACK e se for para você, sua mensagem
* foi enviada com sucesso, passe o token para o vizinho da direita, senão,
* repasse o ACK para o seu vizinho da direita.
*/
public String ReceivedMessage(String msg) {
String[] array = msg.split(";");
switch (array[0].trim()) {
case "4060":
if (queue.getSize() == 0) {
return msg;
} else {
try {
WaitForMessage.acquire();
return queue.RemoveMessage();
} catch (InterruptedException ex) {
Logger.getLogger(MessageController.class.getName()).log(Level.SEVERE, null, ex);
}
}
case "4067":
String aux = array[1].trim();
if (aux.equalsIgnoreCase(nickname)) {
WaitForMessage.release();
return "4060";
} else {
try {
WaitForMessage.acquire();
return queue.RemoveMessage();
} catch (InterruptedException ex) {
Logger.getLogger(MessageController.class.getName()).log(Level.SEVERE, null, ex);
}
return msg;
}
case "4066":
String aux2 = new String(msg).trim();
String[] array2 = aux2.split(";");
String[] restoArray = array[1].split(":");
String remetente = restoArray[0];
String destino = restoArray[1];
String mensagem = restoArray[2];
if (destino.equalsIgnoreCase(nickname)) {
System.out.println("Message from " + remetente + ": " + mensagem);
try {
WaitForMessage.acquire();
return queue.RemoveMessage();
} catch (InterruptedException ex) {
Logger.getLogger(MessageController.class.getName()).log(Level.SEVERE, null, ex);
}
return "4067;" + remetente;
} else {
WaitForMessage.release();
return msg;
}
}
return null;
}
@Override
public void run() {
DatagramSocket clientSocket = null;
byte[] sendData;
/* Cria socket para envio de mensagem */
try {
clientSocket = new DatagramSocket();
} catch (SocketException ex) {
Logger.getLogger(MessageController.class.getName()).log(Level.SEVERE, null, ex);
return;
}
while (true) {
/* Neste exemplo, considera-se que a estação sempre recebe o token
e o repassa para a próxima estação. */
try {
/* Espera time_token segundos para o envio do token. Isso é apenas para depuração,
durante execução real faça time_token = 0,*/
Thread.sleep(time_token * 1000);
} catch (InterruptedException ex) {
Logger.getLogger(MessageController.class.getName()).log(Level.SEVERE, null, ex);
}
/* Converte string para array de bytes para envio pelo socket. */
Scanner scanner = new Scanner(System.in);
String msg = scanner.next().toString();
sendData = msg.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
/* Realiza envio da mensagem. */
try {
clientSocket.send(sendPacket);
} catch (IOException ex) {
Logger.getLogger(MessageController.class.getName()).log(Level.SEVERE, null, ex);
}
/* A estação fica aguardando a ação gerada pela função ReceivedMessage(). */
try {
WaitForMessage.acquire();
} catch (InterruptedException ex) {
Logger.getLogger(MessageController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
Gerenciador de fila de mensagem
package TokenRing;
import java.net.InetAddress;
import java.util.ArrayList;
import javax.print.DocFlavor;
/* Esta classe deve implementar uma fila de mensagens. Observe que esta fila será
* acessada por um consumidor (MessageSender) e um produtor (Classe principal, TokenRing).
* Portanto, implemente controle de acesso (sincronização), para acesso a fila.
*/
public class MessageQueue {
/*Implemente uma estrutura de dados para manter uma lista de mensagens em formato string.
* Você pode, por exemplo, usar um ArrayList().
* Não se esqueça que em uma fila, o primeiro elemente a entrar será o primeiro
* a ser removido.
*/
ArrayList<String> queue = new ArrayList<>();
public MessageQueue(){
}
public void AddMessage(String Message){
/* Adicione a mensagem no final da fila. Não se esqueça de garantir que apenas uma thread faça isso
por vez. */
queue.add(Message);
}
public String RemoveMessage(){
if(queue.size()>0){
String aux = queue.get(0);
return aux;
} else{
return null;
}
}
public int getSize(){
return queue.size();
}
}
Adriano Guterres
Curtir tópico
+ 0
Responder
Posts
11/10/2017
Adriano Guterres
Receiver de mensagem
Classe motriz
package TokenRing;
import java.io.*;
import java.net.*;
import java.util.logging.*;
/* Recebe mensagens do vizinho da esquerda e repassa para a classe MessageController.
* Provavelmente você não precisará modificar esta classe.
*/
public class MessageReceiver implements Runnable{
private MessageQueue queue;
private int port;
private MessageController controller;
public MessageReceiver(MessageQueue t, int p, MessageController c){
queue = t;
port = p;
controller = c;
}
@Override
public void run() {
DatagramSocket serverSocket = null;
try {
/* Inicializa o servidor para aguardar datagramas na porta especificada */
serverSocket = new DatagramSocket(port);
} catch (SocketException ex) {
Logger.getLogger(MessageReceiver.class.getName()).log(Level.SEVERE, null, ex);
return;
}
byte[] receiveData = new byte[1024];
while(true){
/* Cria um DatagramPacket */
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
try {
/* Aguarda o recebimento de uma mensagem. Esta thread ficará bloqueada neste ponto
até receber uma mensagem. */
serverSocket.receive(receivePacket);
} catch (IOException ex) {
Logger.getLogger(MessageReceiver.class.getName()).log(Level.SEVERE, null, ex);
}
/* Converte o conteúdo do datagrama em string.
* Lembre-se, isso apenas funciona porque sabemos que a mensagem recebida tem formato string.
*/
String msg = new String( receivePacket.getData());
/* Neste ponto você possui uma mensagem do seu vizinho da esquerda.
* Passe a mensagem para a classe MessageController, ela deverá decidir
* o que fazer.
*/
System.out.println(controller.ReceivedMessage(msg));
}
}
}
Classe motriz
package TokenRing;
import java.io.*;
import java.util.ArrayList;
import java.util.logging.*;
public class TokenRing {
public static void main(String[] args) throws IOException {
String ip_port;
int port;
int t_token = 0;
boolean token = false;
String nickname;
/* Le arquivo de configuração. */
try ( BufferedReader inputFile = new BufferedReader(new FileReader("ring.cfg"))) {
/* Lê IP e Porta */
ip_port = inputFile.readLine();
String aux[] = ip_port.split(":");
port = Integer.parseInt(aux[1]);
/* Lê apelido */
nickname = inputFile.readLine();
/* Lê tempo de espera com o token. Usado para fins de depuração. Em caso de
execução normal use valor 0. */
t_token = Integer.parseInt(inputFile.readLine());
/* Lê se a estação possui o token inicial. */
token = Boolean.parseBoolean(inputFile.readLine());
} catch (FileNotFoundException ex) {
Logger.getLogger(TokenRing.class.getName()).log(Level.SEVERE, null, ex);
return;
}
/* Cria uma fila de mensagens. */
MessageQueue queue = new MessageQueue();
MessageController controller = new MessageController(queue, ip_port, t_token, token, nickname);
Thread thr_controller = new Thread(controller);
Thread thr_receiver = new Thread(new MessageReceiver(queue, port, controller));
thr_controller.start();
thr_receiver.start();
/* Neste ponto, a thread principal deve ficar aguarando o usuário entrar com o destinatário
* e a mensagem a ser enviada. Destinatário e mensagem devem ser adicionados na fila de mensagens pendentes.
* MessageQueue()
*
*/
}
}
Responder
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)