Java Instant Messenger - 联系人列表

时间:2014-04-07 10:08:31

标签: java

我正在构建我的第一个即时消息应用程序。使用各种教程(The New Boston; Head First Java)我已经成功实现了一个可以在另一个之间发送接收/消息的工作客户端服务器。

我现在希望添加一些稍微高级的功能,例如允许我添加朋友的联系人列表,查看我的朋友何时在线/离线。我试图避免第三方API(例如Smack),因为我希望学习基础知识。遗憾的是,我所阅读的在线教程并不仅仅是设置基本的双方客户端 - 服务器模型。

我的问题是:如何实现链接到我的下面的Server.java和Client.java的基本联系人列表?

非常感谢您的帮助。

Server.java:

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

import java.util.Date;//timestamp functionality


public class Server extends JFrame{ //inherits from JFrame

    //1. Instance Variables

    private JTextField userText; //where messages are typed
    private JTextArea chatWindow; //where messages are displayed
    private String fullTimeStamp = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date());
    //fullTimeStamp - MM = months; mm = minutes; HH = 24-hour clock

    //setting up the streams
    private ObjectOutputStream output; //messages being sent by user
    private ObjectInputStream input; //messages being received by user;

    private ServerSocket server;

    private Socket connection; //Socket = sets up connection between one computer and another.

    //2. Constructor (GUI)
    public Server(){
    super("Mick's Instant Messenger [SERVER]"); //window title
    userText = new JTextField();
    userText.setEditable(false); //you cannot type anything, unless you are connected to someone else
    userText.addActionListener( 
        new ActionListener(){
        public void actionPerformed(ActionEvent event){
            sendMessage(event.getActionCommand());
            userText.setText(""); //Resets editable text field after you send message
        }
        }
    );
    add(userText, BorderLayout.SOUTH);//places user text input (JTextArea) field at bottom
    chatWindow = new JTextArea(15,30); //displays conversation
    add(new JScrollPane(chatWindow));
    chatWindow.setLineWrap(true); //wraps lines when they outgrow the panel width
    chatWindow.setWrapStyleWord(true); //ensures that above line wrap occurs at word end
    setSize(400,320);
    setVisible(true); //set visible on screen
    }

    //3.Setup and Run the Server
    public void StartRunning(){
        try{
            server = new ServerSocket(6789, 100);
            //Client connects at Port # 6789
            //100 = QueueLength - the backlog of clients who can wait at port #6789 to connect to the Server

            //while(true) ... means this while loop is going to run forever
            while(true){
                try{
                    waitForConnection();
                    setupStreams();
                    whileChatting(); //allows messages to pass back and forth through streams
                }catch(EOFException eofException){

                    //connect and have conversation
                    //Display timestamp for disconnection
                    showMessage("\n\n" + fullTimeStamp);
                    showMessage("\nConnection terminated by SERVER! "); //displays end of stream/connection


                }finally{
                    closeCrap();
                }
            }
        }catch(IOException ioException){
            ioException.printStackTrace(); //Displays info where there's an error!
    }
    }

        //4. wait for connection method, then display connection info
        private void waitForConnection() throws IOException{
            showMessage("\n SERVER : Waiting for user(s) to connect... \n "); //tells user Server is waiting for a connection
            connection = server.accept();
            //socket "connection" will accept connections. Creates a socket for each new connection.
            showMessage("Connected with " +connection.getInetAddress().getHostName()); //displays IP address and hostname

        }

        //5. setup streams method.. get streams to send and receive data
        private void setupStreams() throws IOException{
            output = new ObjectOutputStream(connection.getOutputStream());
            //creates pathway to allow connection to whichever computer the 'connnection' socket created.
            output.flush(); //clears data that gets left over in buffer when you try to connect to someone else. Flushes it over to the other person.
            input = new ObjectInputStream(connection.getInputStream());
            //no flush here, because you cannot flush someone else's stream
            showMessage("\n Streams are now setup! \n");

        }

        //6. during conversation method

        private void whileChatting() throws IOException{

            //Display timestamp for connection
            showMessage("\n" + fullTimeStamp);

            String message = "You are now connected! \n ";
            sendMessage(message);
            ableToType(true); //will allow user to type into text box after a connection
            String timeStamp = new java.text.SimpleDateFormat("HH:mm:ss").format(new Date());//timestamp

            do{
                try{
                    message = (String) input.readObject(); //read incoming message as a String and store in 'message' variable.
                    showMessage("\n" + message);//displays each message you receive on a new line
                }catch(ClassNotFoundException classNotFoundException){
                    showMessage("/n I don't know what object the user has sent!");
                }

            //***broken by timestamp?***    
            }while(!message.equalsIgnoreCase("CLIENT " + "[" + timeStamp  + "]" + ": " + "END")); //allows conversation until Client enters "END"

        }

        //7. Close Crap method - close streams and sockets after you are finished chatting
        private void closeCrap(){
            showMessage("\n\n Closing connections... \n");
            ableToType(false);
            try{
                output.close(); //close your stream to other users
                input.close(); //close incoming streams
                connection.close(); //close the socket

            }catch(IOException ioException){
                ioException.printStackTrace();
            }
}
        //8. send message method - send message to client
        private void sendMessage(String message){
            try{

                //writeObject method is built into Java.

                String timeStamp = new java.text.SimpleDateFormat("HH:mm:ss").format(new Date());//timestamp
                output.writeObject("SERVER" + " [" + timeStamp + "]" + ": " + message);
                showMessage("\nSERVER" + " [" + timeStamp + "]" + ": " + message); //shows the ouput message in our conversation window
                output.flush();
            }catch(IOException ioException){
                chatWindow.append("ERROR: Unable to send message!");
            }
        }

        //9. updates chatWindow - instead of creating entirely new GUI each time
        private void showMessage(final String text){
        SwingUtilities.invokeLater(
                new Runnable(){
                    public void run(){
                        chatWindow.setEditable(false); //disallows text editing in chatWindow
                        chatWindow.append(text); //appends text, which was passed in from above
                    }
                }
                );  
}
        //10. Lets user type
        private void ableToType(final boolean tof){
            SwingUtilities.invokeLater(
                    new Runnable(){
                        public void run(){
                            userText.setEditable(tof); //passes in 'true'
                        }
                    }
                    );  

        }
}

Client.java:

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Date; //timestamp functionality

import javax.swing.*;

public class Client extends JFrame { //inherits from JFrame

    //1. Creating instance variables

    private JTextField userText; //where user inputs text
    private JTextArea chatWindow; //where messages are displayed
    private String fullTimeStamp = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date());
    //fullTimeStamp - MM = months; mm = minutes; HH = 24-hour cloc
    private ObjectOutputStream output; //output from Client to Server
    private ObjectInputStream input; //messages received from Server
    private String message ="";
    private String serverIP;
    private Socket connection;

    //2. Constructor (GUI)
    public Client(String host){ //host=IP address of server
        super("Mick's Instant Messenger [CLIENT]");
        serverIP = host; //placed here to allow access to private String ServerIP
        userText = new JTextField();
        userText.setEditable(false);
        userText.addActionListener(
            new ActionListener(){
                public void actionPerformed(ActionEvent event){
                    sendMessage(event.getActionCommand()); //For this to work, must build sendData Method
                    userText.setText(""); //resets userText back to blank, after message has been sent to allow new message(s)
                }
            }

                );
        add(userText, BorderLayout.SOUTH);
        chatWindow = new JTextArea();
        add(new JScrollPane(chatWindow), BorderLayout.CENTER); //allows you to scroll up and down when text outgrows chatWindow
        chatWindow.setLineWrap(true); //wraps lines when they outgrow the panel width
        chatWindow.setWrapStyleWord(true); //ensures that above line wrap occurs at word end
        setSize(400,320);
        setVisible(true);
    }

    //3. startRunning method
    public void startRunning(){
        try{
            connectToServer(); //unlike Server, no need to wait for connections. This connects to one specific Server.
            setupStreams();
            whileChatting();
        }catch(EOFException eofException){


            //Display timestamp for disconnection
            showMessage("\n\n" + fullTimeStamp);
            showMessage("\nConnection terminated by CLIENT! ");


        }catch(IOException ioException){
            ioException.printStackTrace();
        }finally{
                closeCrap();
            }

    }

    //4. Connect to Server
    private void connectToServer() throws IOException{
        showMessage(" \n Attempting connection to SERVER... \n");
        connection = new Socket(InetAddress.getByName(serverIP), 6789);//Server IP can be added later
        showMessage(" Connected to: " +connection.getInetAddress().getHostName() ); //displays IP Address of Server
    }

    //5. Setup streams to send and receive messages
    private void setupStreams() throws IOException{
        output = new ObjectOutputStream(connection.getOutputStream());
        output.flush();
        input = new ObjectInputStream(connection.getInputStream());
        showMessage("\n Streams are now setup! \n");

    }

    //6. While chatting method
    private void whileChatting() throws IOException{


        //Display timestamp for connection
        showMessage("\n" + fullTimeStamp);

        ableToType(true);
        String timeStamp = new java.text.SimpleDateFormat("HH:mm:ss").format(new Date());//timestamp
        do{
            try{
                message = (String) input.readObject(); //read input, treat as String, store in message variable
                showMessage("\n" + message);
            }catch(ClassNotFoundException classNotfoundException){
                showMessage("\n I don't know that object type");
            }

        //***broken by timestamp?***    
        }while(!message.equalsIgnoreCase("SERVER " + "[" + timeStamp  + "]" + ": " + "END")); //Conversation happens until Server inputs 'End'

    }

    //7. Close the streams and sockets
    private void closeCrap(){
        showMessage("\n\nClosing streams and sockets...");
        ableToType(false);//disable typing feature when closing streams and sockets
        try{
            output.close();
            input.close();
            connection.close();
        }catch(IOException ioException){
            ioException.printStackTrace(); //show error messages or exceptions
        }
    }

    //8. Send Messages to Server
    private void sendMessage(String message){
        try{
        String timeStamp = new java.text.SimpleDateFormat("HH:mm:ss").format(new Date());//timestamp
        output.writeObject("CLIENT" + " [" + timeStamp + "]" + ": " + message);
        output.flush();
        showMessage("\nCLIENT" + " [" + timeStamp + "]" + ": " + message);
    }catch(IOException ioexception){
        chatWindow.append("\n Error: Message not sent!");
    }

    }

    //9.change/update chatWindow
    private void showMessage(final String m){
        SwingUtilities.invokeLater(
                new Runnable(){
                    public void run(){
                        chatWindow.setEditable(false); //disallows text editing in chatWindow
                        chatWindow.append(m); //appends text, which was passed in from above
                    }
                }

                );
    }

    //10. Lets user type
            private void ableToType(final boolean tof){
                SwingUtilities.invokeLater(
                        new Runnable(){
                            public void run(){
                                userText.setEditable(tof); //passes in 'true'
}
        }

                        );
            }
}

2 个答案:

答案 0 :(得分:1)

我认为你想要一个持久的联系人列表而不是一个会话。因此,一种解决方案是根据用户名创建帐户并关联id:

示例您的朋友使用名称Fred登录IM,如果这是一个新名称,请将其保存到某处(例如文本文件或简单数据库)

如果您随后将Fred添加为联系人,则需要单独的文本文件或数据库表来保存每个用户的联系人详细信息。您将要做的就是将Fred的ID与您自己的ID联系起来。

然后,当您下次进入IM时,服务器应该从保存的任何地方显示您的联系人列表

答案 1 :(得分:1)

创建文件并存储最近的在线用户,方法是将他们映射到他们聊天的用户。假设Fred正在与XY聊天,所以从下次Fred登录时,他会看到XY已被添加到他的联系人列表中,他应该可以选择在将来删除或阻止它们。 XY也是如此。