Java Socket混合以前的消息最近的帖子

时间:2016-04-24 01:27:57

标签: java sockets chat datagram

您好我正在使用内部IP网络与java聊天但是我发送了一些消息之后发生了一个错误,这个程序混合了之前的消息和新发送的消息,无法找到它的原因。 遵循代码。

Conexao.java

公共类Conexao扩展了Observable {

private String ip;
private int porta;
private String mensagem;

public Conexao(String ip, int porta) {
    this.ip = ip;
    this.porta = porta;
    new Thread(new Recebe()).start();
}

public String getMensagem() {
    return mensagem;
}

public String getIp() {
    return ip;
}

public int getPorta() {
    return porta;
}

public void envia(String texto) {
    new Thread(new Envia(texto)).start();     
}

public void notifica(String mensagem) {
    this.mensagem = mensagem;
    setChanged();
    notifyObservers();
}

class Recebe implements Runnable {

    byte[] dadosReceber = new byte[65508];
    boolean erro = false;
    DatagramSocket socket = null;

    @Override
    public void run() {
        while (true) {
            try {
                socket = new DatagramSocket(getPorta());
            } catch (SocketException ex) {
                Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex);
            }
            erro = false;
            while (!erro) {
                DatagramPacket pacoteRecebido = new DatagramPacket(dadosReceber, dadosReceber.length);
                try {

                    socket.receive(pacoteRecebido);
                    socket.getReceiveBufferSize();
                    byte[] b = pacoteRecebido.getData();
                    String s = "";
                    for (int i = 0; i < b.length; i++) {
                        if (b[i] != 0) {
                            s += (char) b[i];
                        }
                    }

                    String nome = pacoteRecebido.getAddress().toString() + " disse:";
                    notifica(nome + s);
                } catch (Exception e) {
                    System.out.println("erro");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    erro = true;
                }
            }
        }
    }
}

class Envia implements Runnable {

    String texto;

    public Envia(String texto) {
        this.texto = texto;
    }

    @Override
    public void run() {

        byte[] dados = texto.getBytes();

        try {
            DatagramSocket clientSocket = new DatagramSocket();
            InetAddress addr = InetAddress.getByName(getIp());               
            DatagramPacket pacote = new DatagramPacket(dados, dados.length, addr, getPorta());
            clientSocket.send(pacote);
            clientSocket.close();
        } catch (SocketException ex) {
            Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnknownHostException ex) {
            Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

}

JanelaChat.java

公共类JanelaChat扩展javax.swing.JFrame实现Observer {

private Conexao conexao;

public JanelaChat(Conexao conexao) {
    super("chat");
    this.conexao = conexao;
    initComponents();
    conexao.addObserver(this);
    escreve("Chat iniciado com " + conexao.getIp() + ":" + conexao.getPorta());
    mensagemjTextArea.requestFocusInWindow();
}

private void envia() {
    if (!mensagemjTextArea.getText().isEmpty()) {
        conexao.envia(mensagemjTextArea.getText());
        escreve("Você disse: " + mensagemjTextArea.getText());
        mensagemjTextArea.setText("");
    }
}

private void escreve(String texto) {
    chatjTextArea.append(texto + "\n");
    if (!chatjTextArea.getText().isEmpty() && !chatjTextArea.isFocusOwner()) {
        chatjTextArea.setCaretPosition(chatjTextArea.getText().length() - 1);
    }

}

感谢您的关注,对不起我的英语,我希望我能说清楚。

1 个答案:

答案 0 :(得分:0)

您对运输做出了难以理解的假设。 UDP数据报可以多次传送,不按顺序传送,或者根本不传送。如果您需要可靠性,排序,非重复等,请使用TCP。

你还有其他问题。从新接收的数据报构建String的正确方法(假设它只包含字符数据)是:

String s = new String(packet.getData(), packet.getOffset(), packet.getLength());

您不需要所有的空检查:只需要上面的内容。