GARANTIR DESCONTO

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
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

Adriano Guterres

Responder

Posts

11/10/2017

Adriano Guterres

Receiver de mensagem
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

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar