2014-04-07 3 views
0

Я создаю свое первое приложение мгновенных сообщений. Используя различные учебники (New Boston, Head First Java), я успешно реализовал рабочий клиент-сервер, который может отправлять сообщения приема/сообщения между собой.Java Instant Messenger - Список контактов

Теперь я хочу добавить несколько продвинутых функций, таких как список контактов, который позволяет мне добавлять друзей, видеть, когда мои друзья находятся в режиме онлайн/офлайн. Я пытаюсь избежать сторонних 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' 
} 
     } 

         ); 
      } 
} 
+0

Это предложение «Я пытаюсь избежать API» не имеет смысла. _Everything_ - это API. Что именно вы пытаетесь сказать? –

+0

@BoristheSpider: Я имел в виду, что я стараюсь избегать использования сторонних API. Я относительно новичок в этом языке, поэтому извиняюсь, если я вас раздражал, не зная всего, что вы делаете. Я отредактировал свое оригинальное сообщение, чтобы отразить ваш предыдущий комментарий. – mickm

ответ

1

Я предположил бы, что вы хотите постоянный список контактов, а не один на один сеанс только. Поэтому одним из решений было бы создать учетные записи на основе имени пользователя и связать идентификатор:

Пример вашего друга регистрируется в IM с именем Fred, если это новое имя, дайте ему идентификатор и сохраните его где-нибудь (например, текстовый файл или простая база данных)

Если вы добавите Fred в качестве контакта, вам понадобится отдельный текстовый файл или таблица базы данных для хранения контактной информации для каждого пользователя. Все, что вы будете делать, это связывание идентификатора Фреда с вашим.

Затем, когда вы в следующий раз перейти в IM сервер должен вызвать список контактов, где бы он сохраняется

1

Либо создавать файлы и хранить последние онлайн пользователей путем сопоставления их с тем, кого они в чате. Предположим, Fred беседует с X и Y, поэтому со следующего раза, когда Fred войдет в систему, он увидит в своем списке контактов X и Y, и у него должна быть возможность удалить или заблокировать их в будущем. И то же самое должно произойти с X и Y.

Смежные вопросы