如何用纯Java制作基本的即时通讯程序

时间:2011-12-17 04:22:48

标签: java instant-messaging

用赏金重新回答这个问题!我需要一个保持在线的例子,就像一个真正的即时通讯工具!它需要始终准备好使用TCP在任意端口上接收或发送消息到任意地址。 发送/接收消息后,该程序不得退出。

  

Bounty可以为任何能够提供真实,可用的即时通讯工具的人提供最好的例子。


在线查看,我找到的所有资源都是useless tutorialsdead threadsdead tutorialsancient examples,或者告诉程序员使用外部API。 如何从头开始创建基本的即时消息,只使用Java SE?

必须有办法做到这一点,一些示例代码将不胜感激。它只需要执行最简单的任务:检查兼容客户端是否在另一台计算机上处​​于联机状态(用户将提供IP)并向该客户端发送TCP数据包,该客户端将接收并显示其内容。

6 个答案:

答案 0 :(得分:13)

  

当这个问题在2011年首次被问及回答时,它只是“在网上看,我找到的所有资源都无用   教程,死线程,或告诉程序员使用外部   API。“。下面提供的链接符合当时的标准。在评论中进一步讨论。

java socket chat”的前几个Google搜索结果:

或者来自“java 8 chat client”:

在搜索中有很多很多结果。选择一个适合您的需求。如果您愿意,您甚至可以将Google搜索修改为仅显示过去一年的结果。

答案 1 :(得分:8)

我在学习Java时已经做到了这一点,大约10年前。它有效:

Constantes.java:

package jsc;

public interface Constantes {
    public static final String MULTICAST_IP = "224.0.0.1";

    public static final int     MULTICAST_PORTA = 3333;

    public static final String SEPARADOR = "[>>>]";

    public static final int TAMANHO_MENSAGEM = 1024;

    public static final long ESPERA = 3000;

    public static final String ESTOUONLINE = "EstouOnline";

    public static final String DESCONECTANDO = "Desconectando";

    public static final String PRIVADO = "Privado";

}

ControladorThread.java

package jsc;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;

public class ControladorThread extends Thread implements Constantes{
    private MulticastSocket mcSocket;
    private Main main;
    private Vector<Usuario> listaUsuarios;                          // lista de usuários ativos

    public ControladorThread(Main main){
        super("ReceptoraThread_" + main.getNick());
        listaUsuarios = new Vector<Usuario>();
        listaUsuarios.add(new Usuario(main.getNick(), new Date().getTime()));
        this.main = main;

        try{
            mcSocket = new MulticastSocket(MULTICAST_PORTA);
            mcSocket.joinGroup(InetAddress.getByName(MULTICAST_IP));
        } catch(IOException e){
            e.printStackTrace();
        }
    }

    public void run(){
        while(true){
            try{
                byte[] buffer = receberPacote();
                processar(buffer);
                removerUsuariosOciosos();
                atualizarListaUsuarios();
            } catch(IOException e){
                e.printStackTrace();
            }
        }
    }   

    public byte [] receberPacote() throws IOException{
        byte[] buffer = new byte[TAMANHO_MENSAGEM];
        DatagramPacket pacote = new DatagramPacket(buffer, buffer.length);
        mcSocket.receive(pacote);
        return buffer;
    }

    public void processar(byte[] buffer){
        String mensagem = new String(buffer);
        mensagem = mensagem.trim();

        StringTokenizer tokens = new StringTokenizer(mensagem, SEPARADOR);
        String t1 = tokens.nextToken();
        String t2 = tokens.nextToken();

        if(t1.equals(ESTOUONLINE))
            atualizarEstadoUsuario(t2);
        else if(t1.equals(DESCONECTANDO))
            desconectarUsuario(t2);
        else if(t1.equals(PRIVADO)){
            String t3 = tokens.nextToken();
            String t4 = tokens.nextToken();
            if(t3.equals(main.getNick())){
                receberMensagemPrivada(t2, t4);
            }
        }
        else
            main.setTextoEntrada(t1 + " diz: " + t2);
    }

    public void receberMensagemPrivada(String deUsuario, String mensagem){
        main.abrirChatPrivado(main.getNick(), deUsuario, mensagem);
    }

    public boolean atualizarEstadoUsuario(String nomeUsuario){
        int pos;
        for(Iterator i = listaUsuarios.iterator(); i.hasNext(); ){
            Usuario uAux = (Usuario) i.next();
            if(uAux.getNome().equals(nomeUsuario)){
                pos = listaUsuarios.indexOf(uAux);
                listaUsuarios.remove(uAux);
                uAux.setTempoInicio(new Date().getTime());
                listaUsuarios.add(pos, uAux);
                return true;
            }
        }
        listaUsuarios.add(new Usuario(nomeUsuario, new Date().getTime()));
        return false;
    }

    public void removerUsuariosOciosos(){
        Usuario usuario = null;
        for(Iterator i = listaUsuarios.iterator(); i.hasNext(); ){
            usuario = (Usuario) i.next();
            if(new Date().getTime() - usuario.getTempoInicio() > ESPERA){
                desconectarUsuario(usuario.getNome());
                i = listaUsuarios.iterator();
            }
        }
    }

    public void desconectarUsuario(String nomeUsuario){
        for(Iterator i = listaUsuarios.iterator(); i.hasNext(); ){
            Usuario uAux = (Usuario) i.next();
            if(uAux.getNome().equals(nomeUsuario)){
                i.remove();
                break;
            }
        }
    }

    public void atualizarListaUsuarios(){
        Vector<String> sVector = new Vector<String>();
        Usuario uAux = null;
        System.out.println("\nOnline: ");
        for(Iterator i = listaUsuarios.iterator(); i.hasNext(); ){
            uAux = (Usuario) i.next();
            System.out.print( uAux.getNome() + " ");
            sVector.add(uAux.getNome());
        }
        main.setUsuariosOnline(sVector);
    }

    private class Usuario{
        private String nome;
        private long tempoInicio;

        public Usuario(){}

        public Usuario(String nome, long tempoInicio){
            this.nome = nome;
            this.tempoInicio = tempoInicio;
        }

        public String getNome() {
            return nome;
        }
        public void setNome(String nome) {
            this.nome = nome;
        }
        public long getTempoInicio() {
            return tempoInicio;
        }
        public void setTempoInicio(long tempoInicio) {
            this.tempoInicio = tempoInicio;
        }
    }

    public void sair(){
        try {
            mcSocket.leaveGroup(InetAddress.getByName(MULTICAST_IP));
            mcSocket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

EstouOnlineThread.java

package jsc;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

public class EstouOnlineThread extends Thread implements Constantes{
    private MulticastSocket mcSocket;
    private String nick;
    private byte[] buffer;

    public EstouOnlineThread(String nick){
        super("EstouOnlineThread_" + nick);
        this.nick = nick;
        try {
            mcSocket = new MulticastSocket();
        } catch(IOException e) {
            e.printStackTrace();
        } 
    }

    public void run(){
        String saida = ESTOUONLINE + SEPARADOR + nick;
        buffer = saida.getBytes();
        while(true){
            try{
                DatagramPacket estouOnline = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(MULTICAST_IP), MULTICAST_PORTA);
                mcSocket.send(estouOnline);

                System.out.println(saida);
                sleep(ESPERA);
            }
            catch(InterruptedException e){
                e.printStackTrace();
            }
            catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}

MensagemPrivadaFrame.java

package jsc;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;

public class MensagemPrivadaFrame extends Frame implements Constantes{
    private static final long serialVersionUID = 1L;    

    private TextArea entrada;
    private TextField saida;

    private String nomeJanela;
    private String nick;
    private String paraUsuario;
    private MulticastSocket mcSocket;

    private ActionListener saidaListener;
    private WindowAdapter frameListener;

    private boolean estouVivo;      // indica que a janela ainda está ativa

    public MensagemPrivadaFrame(String nick, String paraUsuario){
        super("JSC - Chat com " + paraUsuario);
        setIconImage(Toolkit.getDefaultToolkit().getImage("icone.4"));
        this.nick = nick;
        this.paraUsuario = paraUsuario;
        this.nomeJanela = nick + paraUsuario;

        try {
            mcSocket = new MulticastSocket();
        } catch (IOException e) {
            e.printStackTrace();
        }

        iniciarComponentes();
        estouVivo = true;
    }

    public void setNomeJanela(String nomeJanela){
        this.nomeJanela = nomeJanela;
    }

    public String getNomeJanela(){
        return nomeJanela;
    }

    public String getNick() {
        return nick;
    }

    public void setNick(String nick) {
        this.nick = nick;
    }

    public boolean estouVivo(){
        return estouVivo;
    }

     public void iniciarComponentes(){
        saidaListener = new ActionListener(){
                public void actionPerformed(ActionEvent e){
                    TextField origem = (TextField) e.getSource();
                    enviarMensagem(origem.getText());
                    entrada.append("\n(" + nick + " diz) " + origem.getText());
                    origem.setText("");
                }
        };

        frameListener = new WindowAdapter(){
            public void windowClosing(WindowEvent e){
                estouVivo = false;
                dispose();

            }
        };

        entrada = new TextArea("[JSC] Bate papo privado entre " + nick + " e " + paraUsuario + "\n");
        entrada.setEditable(false);

        saida = new TextField();
        saida.addActionListener(saidaListener);

        addWindowListener(frameListener);
        setLayout(new BorderLayout());
        int x = (int) (Math.random() * 500);
        int y = (int) (Math.random() * 500);
        setBounds(x, y, 400, 300);
        System.out.println(x + " " + y);
        add("Center", entrada);
        add("South", saida);

        setVisible(true);
        saida.requestFocus();
    }

    public void setTextoEntrada(String texto){
        entrada.append("\n" + texto);
        entrada.setCaretPosition(entrada.getText().length());
    }

    public void enviarMensagem(String mensagem){
        try{
            mensagem = PRIVADO + SEPARADOR + nick + SEPARADOR + paraUsuario + SEPARADOR + mensagem;
            byte[] bMensagem = mensagem.getBytes();
            DatagramPacket pacote = new DatagramPacket(bMensagem, bMensagem.length, InetAddress.getByName(MULTICAST_IP), MULTICAST_PORTA);
            mcSocket.send(pacote);
        }
        catch(UnknownHostException e){
            e.printStackTrace();
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }
}

Main.java

package jsc;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.ScrollPane;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;

public class Main extends Frame implements Constantes{
    private static final long serialVersionUID = 1L;

    private TextArea entrada;
    private TextField saida;
    private JList usuariosOnline;
    private ScrollPane usuariosOnlineScroll;

    private WindowAdapter  mainListener;
    private ActionListener saidaListener;
    private MouseAdapter   listListener;

    private MulticastSocket mcSocket;                           // soquete para multicasting
    private Vector<String> listaUsuariosOnline;                 // lista com os nomes de usuários online
    private Vector<MensagemPrivadaFrame> listaJanelasAbertas;   // janelas de conversação privadas abertas
    private String nick;                                        // nome do usuário no chat

    public void setNick(String nick){
        this.nick = nick;
    }

    public String getNick(){
        return nick;
    }

    public Main(String nick){
        super("Java Socket Chat [" + nick + "]");
        setIconImage(Toolkit.getDefaultToolkit().getImage("icone.1"));  

        this.nick = nick;

        listaUsuariosOnline = new Vector<String>();
        listaUsuariosOnline.add(nick);

        listaJanelasAbertas = new Vector<MensagemPrivadaFrame>();

        try{
            mcSocket = new MulticastSocket();
        }
        catch(IOException e){
            e.printStackTrace();
        }

        iniciarComponentes();
        new EstouOnlineThread(nick).start();
        new ControladorThread(this).start();
    }

    public void iniciarComponentes(){
        mainListener = new WindowAdapter(){
            public void windowClosing(WindowEvent e){
                sair();
            }
        };

        saidaListener = new ActionListener(){
            public void actionPerformed(ActionEvent e){
                TextField origem = (TextField) e.getSource();
                enviarMensagem(origem.getText());
                origem.setText("");
            }
        };

        listListener = new MouseAdapter(){
            public void mouseClicked(MouseEvent e){
                if( e.getClickCount() >= 2 ){
                    // abrir a janela para mensagens privadas e passar o id do usuário
                    JList jlAux = (JList) e.getSource();
                    String paraUsuario = (String) jlAux.getSelectedValue();
                    abrirChatPrivado(nick, paraUsuario, null);
                }
            }
        };

        usuariosOnline = new JList(listaUsuariosOnline);
        usuariosOnline.setSize(new Dimension(60, 280));

        usuariosOnlineScroll = new ScrollPane();
        usuariosOnlineScroll.add(usuariosOnline);

        entrada = new TextArea("Olá " + nick);
        entrada.setEditable(false);
        entrada.setSize(300,280);

        saida   = new TextField();

        saida.addActionListener(saidaListener);
        usuariosOnline.addMouseListener(listListener);
        usuariosOnline.setMinimumSize(new Dimension(60, 250));
        addWindowListener(mainListener);

        setSize(400, 300);
        setLayout(new BorderLayout());
        add("North", new JLabel("Java Socket ChatO"));
        add("Center", entrada);
        add("South", saida);
        add("East", usuariosOnlineScroll);

        setVisible(true);
        requestFocus();
    }

    public void enviarMensagem(String mensagem){
        try{
            mensagem = nick + SEPARADOR + mensagem;
            byte[] bMensagem = mensagem.getBytes();
            DatagramPacket pacote = new DatagramPacket(bMensagem, bMensagem.length, InetAddress.getByName(MULTICAST_IP), MULTICAST_PORTA);
            mcSocket.send(pacote);
        }
        catch(UnknownHostException e){
            e.printStackTrace();
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }

    private void desconectando(){
        try{
            String mensagem = "Desconectando" + SEPARADOR + nick;
            byte[] bMensagem = mensagem.getBytes();
            DatagramPacket pacote = new DatagramPacket(bMensagem, bMensagem.length, InetAddress.getByName(MULTICAST_IP), MULTICAST_PORTA);
            mcSocket.send(pacote);
        }
        catch(UnknownHostException e){
            e.printStackTrace();
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }

    public void abrirChatPrivado(String nick, String paraUsuario, String mensagem){
        removerJanelasInativas();   
        if(nick.equals(paraUsuario)){
            JOptionPane.showMessageDialog(null, "Você não pode abrir um janela de conversação para você mesmo!", "Burro!", JOptionPane.ERROR_MESSAGE);
            return;
        }
        String nome = nick + paraUsuario;
        MensagemPrivadaFrame janela = null;
        for(Iterator i = listaJanelasAbertas.iterator(); i.hasNext();){
            janela = (MensagemPrivadaFrame) i.next();
            if(nome.equals(janela.getNomeJanela())){
                System.out.println(nick + " - " + janela.getNomeJanela() + " - " + janela.toString());
                janela.setTextoEntrada("(" + paraUsuario + " diz) " + mensagem);
                //janela.requestFocus();
                return;
            }
        }

        janela = new MensagemPrivadaFrame(nick, paraUsuario);

        if(mensagem != null)
            janela.setTextoEntrada("(" + paraUsuario + " diz) " + mensagem);

        listaJanelasAbertas.add(janela);
        //janela.requestFocus();
    }

    public void removerJanelasInativas(){
        MensagemPrivadaFrame janela = null;
        for(Iterator i = listaJanelasAbertas.iterator(); i.hasNext(); ){
            janela = (MensagemPrivadaFrame) i.next();
            if( !janela.estouVivo()){
                i.remove();
            }
        }
    }

    public void setTextoEntrada(String texto){
        entrada.append("\n" + texto);
        entrada.setCaretPosition(entrada.getText().length());
    }

    public void setUsuariosOnline(Vector<String> listaUsuariosOnline){
        usuariosOnline.setListData(listaUsuariosOnline);
    }

    public void sair(){
        desconectando();
        dispose();
        System.exit(0);
    }

    public static void main(String args[]){
        String nick = JOptionPane.showInputDialog("Digite seu nome (max. 20 caracteres): ");
        if(nick != null && !nick.equals("")){
            if(nick.length() > 20)
                nick = nick.substring(0, 20);
            new Main(nick);
        }
        else
            JOptionPane.showMessageDialog(null, "É necessário informar um nome para entrar no bate-papo");
        //System.exit(0);
    }
}

如今,我并不为代码感到骄傲,但它确实有效。

修改

正如一些人所建议的那样,我已经进行了一些代码改进(重构)并在GitHub: https://github.com/jaumzera/javasocketchat上发布了项目

答案 2 :(得分:2)

嗯,我很想引导你去实现imap协议的服务器的java实现(例如gavamail)。但是,这个cources,也可能有资格作为&#34; old&#34;代码,肯定会杀死你的期望(作为一个非标准的解决方案)。然而,它是一个适当的参考,符合您的(简洁)规范。

我们有什么?

我们需要一个应该在java中的解决方案。 它必须实现基本的即时消息系统。

后者存在问题,因为它涵盖了非常广泛的功能。但是&#34;基本&#34;似乎允许最低限度的解决方案。

那么什么是最低限度的即时通讯系统?让我们试试以下内容:

  • 发布和检索邮件的客户。
  • 存储用于(稍后)检索的已发布消息的服务器

我们还需要一个客户如何识别正确服务器的策略。对于后一方面,最简单的解决方案是使用&#34; central&#34;服务器具有众所周知的地址。对于更复杂的情况,我们需要将服务器和/或客户端功能分布在多个实例中,并设计一个方案或策略来识别正确的通信实例。

我们遗漏了更复杂的语义,例如让不同的用户或消息与类别或标签系统相关。

现在,我们有两个组成部分:

实现两个入口点的服务器:

  1. POST_MESSAGE
    从客户端接收消息并存储以供以后检索 这个immediatley正在询问存储此类消息的位置的问题(在数据库或文件系统中用于持久性,或仅仅在内存中用于&#34; 消息,只要服务器已启动&#34;语义)

  2. LOOKUP_MESSAGE
    从存储的消息中选择一个合适的消息(最好是未读的消息)并返回给呼叫者 这也可以返回一组消息(但是考虑在呼叫者有严重积压的消息的情况下限制这样的设置)
    可能需要通过标记消息或在客户端保持已查看的状态来跟踪已经读取的消息。这甚至可以像保持最后一条消息的时间或顺序一样简单,并将此信息与LOOKUP_MESSAGE请求一起发送。

  3. 客户需要一方面与用户进行交互,另一方面需要与服务进行交互。

    将从用户那里获取新消息(可能是在显式请求(例如发送按钮)上,并在相关服务器上调用POST_MESSAGE服务。

    它也可能(可能定期,也可能是明确请求(例如,用户正在启动客户端))轮询服务器以获取新消息。 (或者,您可以设计一个单独的通知服务,服务器使用该服务通知客户新消息。适合您的需求&#34;超出您的要求。)

    那就是它。

    因此,基于TCP的客户端/服务器应用程序的任何示例都将成为直接实现的完美起点。

    我还应该提到,您可以在客户端中删除规范逻辑,并将用户交互委托给标准浏览器,并将客户端应用程序逻辑实现到(Web)服务器实例(与服务器部分一起或分开)。尽管如此,根据上述最低规范,您仍将拥有(客户端/服务器)逻辑功能。

    您应该注意的另一个方面是:

    你提到了一些评论&#34; host&#34;和&#34;客人&#34;当前信使示例中可用的属性。这实际上是与这些信使一起提供的标记系统的逻辑结构。消息仍然从客户端发送到服务器,然后由其他客户端检索。客户端是否可以查看消息取决于客户端是否有资格使用特定标记。例如,向您的联系人发送消息(用户b)只是使用标记&#34; for_user_b&#34;标记消息。因此只有海报才能看到它,任何人也可以阅读&#34; for_user_b&#34;标记消息(在我们的示例中为用户b)。因此,请注意,邮件系统的逻辑结构由访问和分发策略决定,而不是由物理分发结构决定!

答案 3 :(得分:2)

我甚至不确定这个问题是否仍在使用,或者我喜欢这项任务,我想:

  

为什么不呢?

这是我的实现,尽可能简单但不遗漏基本部分。 用纯Java编写,利用其余的Sockets,Threads和SynchronizedList:

SimpleChat.java(Main)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class SimpleChat {

private static boolean isRunning = true;
private static Sender sender;
private static Receiver receiver;

public static void main(String[] args) throws IOException {

    if(args.length < 3){
        showUsage();
    }

    try {
        receiver = new Receiver(Integer.parseInt(args[1]));
        sender = new Sender(args[0], args[2], Integer.parseInt(args[3]));
    } catch (InterruptedException e) {
        showUsage();
    }

    // Read user input
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    System.out.println("Chat started. Type '\\exit' to quit.");

    while(isRunning) {
        String input = br.readLine();

        if(input.equals("\\exit")){
            receiver.stop();
            sender.stop();
            isRunning = false;
        } else {
            sender.sendMessage(input);
        }
    }   
}

static void showUsage(){
    System.out.println("Usage: java SimpleChat.java listening_port target_IP target_port");
    System.exit(1);
}

}

Receiver.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Receiver {

private boolean isRunning = true;

public Receiver(int listeningPort) throws IOException {

    Runnable receiverT = new Runnable() {
        public void run() {

            ServerSocket serverSocket;
            try {
                serverSocket = new ServerSocket(listeningPort);
                Socket clientSocket = serverSocket.accept();
                BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

                while(isRunning) {
                    try {
                        System.out.println(in.readLine());
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

        }
    };

    new Thread(receiverT).start();
}

public void stop(){
    isRunning = false;
}


}

Sender.java

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class Sender {

private boolean isRunning = true;
private volatile List<String> msgs;

public Sender(String username, String targetIP, int targetPort) throws InterruptedException, UnknownHostException, IOException {
    msgs = Collections.synchronizedList(new ArrayList<String>());

    Runnable senderT = new Runnable() {
        public void run() {
            try {
                Socket socket = new Socket(targetIP, targetPort);
                PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

                while(isRunning) {
                    synchronized(msgs){
                        Iterator<String> it = msgs.iterator();

                        while(it.hasNext()){
                            out.println(username + ": " + it.next());
                        }

                        // Clear messages to send
                        msgs.clear();
                    }
                }

                out.close();
                socket.close();
            } catch (UnknownHostException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

        }
    };

    new Thread(senderT).start();
}

public void stop(){
    isRunning = false;
}

public void sendMessage(String msg){
    synchronized(msgs){
        msgs.add(msg);  
    }
}
}

正如'showUsage()'所说,使用此程序如下:

java SimpleChat.java username listening_port target_ip target_port

示例:

java SimpleChat.java Supuhstar 1234 127.0.0.1 1234

[与自己交谈]

答案 4 :(得分:1)

我认为你应该澄清一些关于“基本即时通讯程序”究竟是什么意思的细节,以及你对这个项目的实际目标。

在2011年的评论中,您提到应该没有“中心枢纽”,但在最近的评论中,您说您希望更多符合Skype或iMessage的内容,用户无需了解哪些内容peer是服务器......技术上可以(使用mdns,dlna或ssdp等协议)使程序透明地搜索本地网络以查找潜在的现有服务器节点,并将其连接到服务器对等体(如果有),或者将自己建立为本地服务器,以便其他节点连接到它。例如Apple iChat的Bonjour协议如何使用。然而,这是一个相当复杂的实施方案,并且绝对不符合当前大众市场消息传递计划所做的工作。

同样在用户之间建立直接的对等通信会带来一些实际问题(特别是因为防火墙和NAT,但也存在机密性和安全性问题)。因此,大多数协议通过中央服务器中继大多数消息,并仅为了文件传输和音频/视频呼叫而协商直接连接。

出于所有这些原因,除非您只是寻找两个主机之间本地网络通信的示例,否则您肯定需要两个不同的程序:服务器和客户端。

然后,假设我的假设是正确的,还有另外两个问题需要澄清。首先,您是否有实际的理由自己设想协议,或者是否可以接受实现现有协议(例如XMPP,IRC,SIMPLE ......有吨)。尽管这些协议最初可能看起来非常复杂,但几乎总是可以仅实现这些协议的功能/消息的子集。自己设计一个天真的网络协议并不困难,但是你必须经历大量的潜在错误(主要是效率低下,不完整和其他小问题)。也许这确实是你的目标(即从头开始设计网络协议获得经验),但除非是这样,否则你应该认真选择实现现有的协议。实际上,使用现有协议不仅可以避免此类设计错误,而且更好的是,您将从其他人(通常是经验丰富的协议设计人员)如何实际解决他们遇到的问题中获得重要的知识。使用现有协议还可以使您更容易,更有趣地开发该程序,因为您将能够通过连接/到官方客户端/服务器实现来独立测试您的客户端和服务器程序。您还可以利用流量嗅探工具中的现有协议解码器来调试通过的消息。

第二个重要问题是您希望服务器程序的实际程度,最重要的是持久性。服务器是否应维护持久的用户列表并对其进行身份验证?服务器是否应该为每个用户存储允许的联系人列表?服务器是否应允许存储针对当前处于脱机状态或在该时刻无法访问的对等方的消息?真正的消息服务器程序通常会做这些事情,虽然实现这样的机制并不是很困难,但最好在程序架构的设计早期考虑。例如,如果您确定这些功能确实是可取的,那么您可能会立即围绕持久性消息队列引擎设计服务器,例如ActiveMQ ...

我知道这不是你要求的例子,但我仍然希望这些想法对你有所帮助。

答案 5 :(得分:0)

如前所述,你需要做很多事情才能真正开始聊天 但我相信你想要开始一些事情。如果你知道另一个&#34;客户端的地址和端口&#34;这很容易。
极简单&#34;聊天&#34;实施

Random r = new Random();
SelectElement s = new SelectElement(ddlChooseStore_Cart);
s.SelectByIndex(r.Next());