Kamis, 08 November 2012

Aplikasi Chatting dengan Java berbasis Command Line

java
Saya akan membahas mengenai Aplikasi Program Chatting menggunakan Java berbasis Command Line yang merupakan tugas mata kuliah Pemrograman Jaringan. Sedikit Penjelasan tentang program ini, pada intinya sama dengan aplikasi chatting sederhana lain yakni komunikasi antar server dengan client, namun ada sedikit modifikasi atau penambahan listing program agar bisa digunakan lebih dari dua client serta adanya file log untuk menyimpan pesan offline apabila user atau client tersebut sedang tidak online. Program java ini terdiri dari 4 file .java yang saling berkaitan, yaitu:
  1. UDPServer.java
  2. UDPClient.java
  3. UdpChat.java
  4. SendThread.java


Untuk menjalankan program/aplikasi ini, dimulai dengan mengaktifkan server terlebih dahulu. Yaitu menjalankan file UdpChat.java, Berikut contoh perintahnya:
Penjelasan:
argumen -s menandakan untuk mengaktifkan server
port yang digunakan oleh server adalah 9090

Kemudian perintah berikut untuk menjalan client pertama sebagai berikut:
  
Kemudian untuk client kedua.
Penjelasan:
argumen -c berarti adalah untuk menjalan client.
kemudian nama user/client (tidak boleh sama).
alamat IP (disini dipakai localhost) misal: 127.0.0.1 dll
port server (harus sama dengan server yang baru saja diaktifkan)
port client masing-masing (setiap client harus berbeda port nya)

Lalu untuk melihat list user yang online atau offline

Sekarang akan mencoba mengirim pesan dari user satu ke user lain yang sedang online.
User lain menanggapi pesan

Misalkan user/client pertama akan offline,
Untuk melihat status on/off pada tabel user.

Sekarang user/client kedua ingin mengirim pesan ke user pertama yang sudah offline, pesan tersebut akan tersimpan di server untuk kemudian disampaikan kepada user pertama jika sudah online lagi.
Apabila user pertama tadi sudah online lagi, pesan offline dari user kedua akan diterima

Contoh kasus:
  • Bagaimana kerja server untuk bisa menyimpan pesan yang dikirimkan salah satu user/client kepada user yang sedang offline?
Untuk ini, yang berperan adalah file UDPServer.java dengan bantuan file SendThread.java, server akan membuat file .txt yang berfungsi menyimpan pesan offline namun hanya bersifat sementara dan akan hilang apabila user yang offline telah online kembali dan pesan offline disampaikan.
berikut potongan program untuk menyimpan pesan offline.
public static void saveMessage(String output) throws IOException
    {
        String[] values = output.split(" ");
        String toClient = values[1];
        String fromClient = values[2];
        int index = 7 + values[1].length()+ values[2].length();
        DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        Date date = new Date();
       
        String message = fromClient + ": <" +dateFormat.format(date) + "> " + output.substring(index);
       
        /* Each client get its own txt file */
        String filename = toClient+".txt";
              File txt = null;
        BufferedWriter writer = null;
        try
        {
             writer = new BufferedWriter(new FileWriter(filename, true));
        }
              /* If file doesn't exist, create a new one */
        catch (FileNotFoundException e)
        {
            txt = new File(filename);
            writer = new BufferedWriter (new FileWriter(txt, true));
                 }
        writer.write(message);
        writer.newLine();
        writer.close();
          }
berikut class potongan kode untuk membaca pesan offline
public static void readMessage(String client) throws IOException
    {
        String filename = client+".txt";

        /* check if txt file exists, if yes, send everything in it to client and delete file */
        try
        {
            BufferedReader in = new BufferedReader(new FileReader(filename));
          ArrayList<Serializable> list = hm.get(client);
           
            //Get the ip of current key
            InetAddress ip = (InetAddress) list.get(1);   
           
            //get the port of the current key
            int p = Integer.parseInt((String) list.get(2));
           
            String output = "Kamu mempunyai pesan";
            byte[] sendData  = new byte[1024];
            sendData = output.getBytes(); 
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ip, p);
            try
            {
                serverSocket.send(sendPacket);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
          String message;
            while ((message = in.readLine()) != null)
            {
                sendData = message.getBytes(); 
                sendPacket = new DatagramPacket(sendData, sendData.length, ip, p);
               
                try
                {
                    serverSocket.send(sendPacket);
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
                           }
           
            in.close();
                       File txt = new File (filename);
            txt.delete();
                              }
       
        /* If not, do nothing */
        catch (FileNotFoundException e)
        {
            //nothing
        }
    }
file text tersebut akan otomatis bernama sesuai nama user yang sedang offline.
  • Program/Aplikasi Chatting ini terdapat 4 file yang berada dalam satu directory, misalkan file server dan file client dipisah ke folder yang berbeda, apakah aplikasi ini masih bisa berjalan?
Jawabannya bisa, aplikasi chatting ini tidak terpaku dengan satu folder saja, yang penting port dan IP address sudah benar dan dapat digunakan, namun penempatan file ke masing-masing folder harus sesuai kebutuhan.
directory server.

directory client.

  • Bagaimana jika menggunakan aplikasi ini dari komputer client yang berbeda? bukan dari satu komputer.
Syaratnya komputer harus sudah terhubung dan terkoneksi lalu untuk alamat IP bisa menyesuaikan. Pada saat login ke server, client harus mendeklarasikan argumen menggunakan alamat IP nya sendiri, bukan IP localhost, dengan begitu akan bisa berkomunikasi dengan komputer satunya.

Source Code.

UDPServer.java
import java.io.*; 
import java.net.*; 
import java.text.*;
import java.util.*;
  
/**
 * Server class that provides the functionalities of a UDPServer
 *
 */
public class UDPServer 
{ 
 /* local hashmap of all clients */
 static HashMap> hm = new HashMap>();

 /* server Socket */
 static DatagramSocket serverSocket = null;
 static byte[] receiveData = new byte[1024]; 
 
 public UDPServer (int port) throws Exception 
 { 
  System.out.println(">>> [Server dimulai...]");
  
  try  
  {
   serverSocket = new DatagramSocket(port);
  }
  catch (BindException e)
  {
   System.out.println(">>> [Socket Sudah digunakan, keluar...]");
   System.exit(0);
  }

  while(true) 
  { 
   /* Server receives a packet */
   DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); 
   serverSocket.receive(receivePacket); 
 
   String sentence = new String(receivePacket.getData(), 0, receivePacket.getLength());
   InetAddress IPAddress = receivePacket.getAddress(); 
   
   /* if packet is to register */
   if (sentence.startsWith(".register"))
   {
    
    String[] values = sentence.split(" ");
    boolean on = false;
    
    /* if client exists, check to see if client is on */
    if (hm.get(values[1]) != null)
    {
     ArrayList list = hm.get(values[1]);
     
     InetAddress toIP = (InetAddress) list.get(1); 
     int toPort = Integer.parseInt((String) list.get(2)); 

     /* if client is on, duplicate clientnames can't register */
     if (checkAlive(values[1], toIP, toPort))
     {
      String output = "[Nama panggilan sudah diambil.]";
      byte[] sendData  = new byte[1024];
      
      sendData = output.getBytes();  
     
      DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, receivePacket.getPort()); 
      try 
      {
       serverSocket.send(sendPacket);
      } 
      catch (IOException e) 
      {
       e.printStackTrace();
      }
      on = true;
     }
     
     /* if client is off */
     else
     {
      on = false;
     }
          
    }
    
    /* Allow registration if client is not on or does not exist */
    if (!on)
    {
     registration (sentence, IPAddress);
     
     String output = "[Selamat datang, Anda terdaftar.]";
     byte[] sendData  = new byte[1024];
     
     sendData = output.getBytes();  
     
     DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, receivePacket.getPort()); 
     try 
     {
      serverSocket.send(sendPacket);
     } 
     catch (IOException e) 
     {
      e.printStackTrace();
     } 
     
     readMessage(sentence.split(" ")[1]);
    }
   }
   
   /* If a client requests to dereg */
   if (sentence.startsWith(".deregister"))
   {
    registration (sentence, IPAddress);
    
    String output = "[Anda Offline. Bye.]";
    byte[] sendData  = new byte[1024];
    
    sendData = output.getBytes();  
    
    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, receivePacket.getPort()); 
    try 
    {
     serverSocket.send(sendPacket);
    } 
    catch (IOException e) 
    {
     e.printStackTrace();
    } 
    
   }
   
   /* If a client wants to start offline chatting */
   if (sentence.startsWith(".off"))
   {
    clientLookUp(sentence, IPAddress, receivePacket.getPort());
   }
   
   /* If a client responds to checkAlive */
   if (sentence.equals(".alive!"))
   {
    ack = true;
   }
  } 
 } 
  
 /**
  * Builds and maintains the hashmap of client information. Pushes updates out
  * whenever the hashmap gets updated.
  * @param sentence - incoming client information
  * @param IPAddress - IP of client
  */
 private static void registration(String sentence, InetAddress IPAddress)
 {
  String[] values = sentence.split(" ");
  
  ArrayList list = new ArrayList();
  
  list.add (values[1]);
  list.add(IPAddress);
  list.add (values[2]);
  list.add(values[3]);
           
  hm.put(values[1], list);
          
  list = new ArrayList();
  
  /* Traverse through the entire hashmap */
  Iterator iterator = hm.keySet().iterator();          
  while (iterator.hasNext()) 
  {  
   //Current Key
   String key = iterator.next().toString();
   
   //Key's values
   list = (ArrayList) hm.get(key); 
   
   //get the status of the current key
   String status = (String) list.get(3);
   
   //Broadcast to clients that are online
   if (status.equalsIgnoreCase("on"))
   {
    //Get the ip of current key
    InetAddress ip = (InetAddress) list.get(1); 
    
    //get the port of the current key
    int p = Integer.parseInt((String) list.get(2)); 

    //traverse through the original HashMap
    Iterator iterator2 = hm.keySet().iterator(); 
    while (iterator2.hasNext())
    {
     String value = hm.get(iterator2.next().toString()).toString();  
     String output = ".hash, " + value.substring(1, value.length()-1);  
     
     byte[] sendData  = new byte[1024];
     
     sendData = output.getBytes();  
     
     DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ip, p); 
     try 
     {
      //Update client with new table
      serverSocket.send(sendPacket);
     } 
     catch (IOException e) 
     {
      e.printStackTrace();
     } 
    }
    
    byte[] sendData  = new byte[1024];
    String output = "[Tabel Klien diperbarui.]";
    sendData = output.getBytes();  
    
    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ip, p); 
    try 
    {
     serverSocket.send(sendPacket);
    } 
    catch (IOException e) 
    {
     e.printStackTrace();
    }
 
   }
  }
 }
  
 /**
  * Resends hashmap if a client is sending off messages to a client that is already on
  * @param client - name of destination client
  * @param ip - ip of out of synced client
  * @param p - port of out of synced client
  */
 private static void sendTable(String client, InetAddress ip, int p)
 {
  String output = "[Client " + client + " sudah ada!!]";
  
  byte[] sendData  = new byte[1024];
  sendData = output.getBytes();  
  
  DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ip, p); 
  try 
  {
   serverSocket.send(sendPacket);
  } 
  catch (IOException e) 
  {
   e.printStackTrace();
  }
  
  Iterator iterator = hm.keySet().iterator(); 
  while (iterator.hasNext())
  {
   String value = hm.get(iterator.next().toString()).toString();  
   output = ".hash, " + value.substring(1, value.length()-1);  
   
   sendData  = new byte[1024];
   sendData = output.getBytes();  
   
   sendPacket = new DatagramPacket(sendData, sendData.length, ip, p); 
   try 
   {
    serverSocket.send(sendPacket);
   } 
   catch (IOException e) 
   {
    e.printStackTrace();
   } 
  }
  
  sendData  = new byte[1024];
  output = "[Tabel Klien diperbarui.]";
  sendData = output.getBytes();  
  
  sendPacket = new DatagramPacket(sendData, sendData.length, ip, p); 
  try 
  {
   serverSocket.send(sendPacket);
  } 
  catch (IOException e) 
  {
   e.printStackTrace();
  }
 }

 /**
  * Looks up client and determine if client is off or not
  * @param sentence - incoming messages
  * @param IPAddress - IP of incoming client
  * @param port - port incoming client
  * @throws IOException
  */
 private static void clientLookUp(String sentence, InetAddress IPAddress, int port) throws IOException
 {
  String[] values = sentence.split(" ");
  String toClient = values[1];
    
  ArrayList list = hm.get(toClient);
  
  String status = (String) list.get(3);

  InetAddress toIP = (InetAddress) list.get(1); 
  
  int toPort = Integer.parseInt((String) list.get(2)); 
  
  /* If client is off according to the table */
  if (status.equals("off"))
  {
   /* If client is off just like the table initiate offline chat*/
   if (!checkAlive (toClient, toIP, toPort))
   {
    saveMessage (sentence);
    
    String output = "[Pesan diterima oleh server dan disimpan]";
    byte[] sendData  = new byte[1024];
    sendData = output.getBytes();  
    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); 
    try 
    {
     serverSocket.send(sendPacket);
    } 
    catch (IOException e) 
    {
     e.printStackTrace();
    }
   }
   
   /* If client is on, inform original sender, then update and broadcast table */
   else
   {
    String output = "[Client " + toClient + " sudah ada!!]";
    
    byte[] sendData  = new byte[1024];
    sendData = output.getBytes();  
    
    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); 
    try 
    {
     serverSocket.send(sendPacket);
    } 
    catch (IOException e) 
    {
     e.printStackTrace();
    }
    
    updateHash(toClient, "on");

   }
   
  }
  
  /* If client is on according to the table */
  else
  {
   /* If client is indeed on, update the misinformed client's table */
   if (checkAlive (toClient, toIP, toPort))
    sendTable (toClient, IPAddress, port); 
   
   /* If client is off, unlike the table values; initiate offline chat and update broadcast table */
   else 
   {
    saveMessage (sentence);
    
    String output = "[Pesan diterima oleh server dan disimpan]";
    byte[] sendData  = new byte[1024];
    sendData = output.getBytes();  
    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); 
    try 
    {
     serverSocket.send(sendPacket);
    } 
    catch (IOException e) 
    {
     e.printStackTrace();
    }
    
    updateHash(toClient, "off");
   }

  }
 }
 
 /**
  * If client is off, save messages to a txt file with timestamp and the client it is from
  * If file doesn't exist, create a new one
  * If a file does exit, append to it
  * @param output
  * @throws IOException
  */
 public static void saveMessage(String output) throws IOException
 {
  String[] values = output.split(" ");
  String toClient = values[1];
  String fromClient = values[2];
  
  int index = 7 + values[1].length()+ values[2].length();

  DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
  Date date = new Date();
  
  String message = fromClient + ": <" +dateFormat.format(date) + "> " + output.substring(index);
  
  /* Each client get its own txt file */
  String filename = toClient+".txt";
  
  File txt = null;
  BufferedWriter writer = null;
  try
  {
    writer = new BufferedWriter(new FileWriter(filename, true));
  }
  
  /* If file doesn't exist, create a new one */
  catch (FileNotFoundException e)
  {
   txt = new File(filename);
   writer = new BufferedWriter (new FileWriter(txt, true));
   
  }

  writer.write(message);
  writer.newLine();
  writer.close();
  
 }
 
 /**
  * When a client goes on, check to see if a txt file exists
  * if it does, get the messages and send them
  * if not, do nothing
  * @param client
  * @throws IOException
  */
 public static void readMessage(String client) throws IOException
 {
  String filename = client+".txt";

  /* check if txt file exists, if yes, send everything in it to client and delete file */
  try 
  {
   BufferedReader in = new BufferedReader(new FileReader(filename));
   
   
   ArrayList list = hm.get(client);
   
   //Get the ip of current key
   InetAddress ip = (InetAddress) list.get(1); 
   
   //get the port of the current key
   int p = Integer.parseInt((String) list.get(2));
   
   String output = "Kamu mempunyai pesan";
   byte[] sendData  = new byte[1024];
   sendData = output.getBytes();  
   DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ip, p); 
   try 
   {
    serverSocket.send(sendPacket);
   } 
   catch (IOException e) 
   {
    e.printStackTrace();
   } 
   

   String message;
   while ((message = in.readLine()) != null)
   {
    sendData = message.getBytes();  
    sendPacket = new DatagramPacket(sendData, sendData.length, ip, p); 
    
    try 
    {
     serverSocket.send(sendPacket);
    } 
    catch (IOException e) 
    {
     e.printStackTrace();
    } 
    
   }
   
   in.close();
   
   File txt = new File (filename);
   txt.delete();
   
   
  } 
  
  /* If not, do nothing */
  catch (FileNotFoundException e) 
  {
   //nothing
  }
 }
 
 /**
  * Check if client is alive by sending a packet, wait 500msec
  * if no response, then client is not alive.
  * @param toClient - Destination client
  * @param toIP - client's IP
  * @param toPort - client's port
  * @return online status
  */
 public static boolean checkAlive(String toClient, InetAddress toIP, int toPort)
 {
  String output = ".alive?";
  byte[] sendData  = new byte[1024];
  sendData = output.getBytes();  
  DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, toIP, toPort); 

  
  try 
  {
   ack = false;
   serverSocket.send(sendPacket);
  } 
  catch (IOException e) 
  {
   e.printStackTrace();
  }
  
  
  boolean done = false;
  while (!done)
  {
   if (ack)
   {
    done = true; 
   }
   else
   {
    /* Wait for 500msec only once */
    if (counter < 1)
    {
     try 
     {
      Thread.sleep(500);
     } 
     catch (InterruptedException e) 
     {
      e.printStackTrace();
     }
     counter++;
    }
    else
     done = true;
   }
  }
  
  counter = 0;
  
  return ack; 
 }
 
 /**
  * If a client is on while off on the table, update and broadcast
  * @param client - client
  * @param newStatus - correct status
  */
 public static void updateHash(String client, String newStatus)
 {
  ArrayList list = hm.get(client);
  
  list.set(3, newStatus);
           
  hm.put(client, list);
          
  Iterator iterator = hm.keySet().iterator();          
  while (iterator.hasNext()) 
  {  
   //Current Key
   String key = iterator.next().toString();
   
   //Key's values
   list = (ArrayList) hm.get(key); 
   
   //get the status of the current key
   String status = (String) list.get(3);
   
   if (status.equalsIgnoreCase("on"))
   {
    //Get the ip of current key
    InetAddress ip = (InetAddress) list.get(1); 
    
    //get the port of the current key
    int p = Integer.parseInt((String) list.get(2)); 

    //traverse through the original HashMap
    Iterator iterator2 = hm.keySet().iterator(); 
    while (iterator2.hasNext())
    {
     String value = hm.get(iterator2.next().toString()).toString();  
     String output = ".hash, " + value.substring(1, value.length()-1);  
     
     byte[] sendData  = new byte[1024];
     
     sendData = output.getBytes();  
     
     DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ip, p); 
     try 
     {
      serverSocket.send(sendPacket);
     } 
     catch (IOException e) 
     {
      e.printStackTrace();
     } 
    }
    
    byte[] sendData  = new byte[1024];
    String output = "[Tabel Klien diperbarui.]";
    sendData = output.getBytes();  
    
    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ip, p); 
    try 
    {
     serverSocket.send(sendPacket);
    } 
    catch (IOException e) 
    {
     e.printStackTrace();
    }
 
   }
  }
 }

 static int counter = 0;
 static boolean ack = false;
 
 }  


UDPClient.java
import java.net.*;
  
/**
 * Class that provides functionalities of a UDPClient
 * Also acts as a receive thread and parses all incoming messages
 *
 */
public class UDPClient 
{
 public UDPClient(String hostname, InetAddress ip, int srvPort, int clientPort ) throws Exception 
    { 
  DatagramSocket clientSocket = null; 
  
  try
  {
   clientSocket = new DatagramSocket( clientPort );
  }
  catch (BindException e)
  {
   System.out.println(">>> [Alamat sudah dipakai, keluar...]");
   System.exit(0);
  }
  
  String nickname = hostname;
  int myPort = clientPort;
  byte[] receiveData = new byte[1024];
  
  InetAddress serverIP = ip;
  int serverPort = srvPort;

  SendThread sender = new SendThread (clientSocket, nickname, serverIP, serverPort, myPort);
  Thread s = new Thread (sender);
  s.start();
  
  
  System.out.println(">>> [Mendaftar...]");
  System.out.print(">>> ");
  
  while (true)
  {

    DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); 
 
    clientSocket.receive(receivePacket); 
       
    String sentence = new String(receivePacket.getData(), 0, receivePacket.getLength());
       
    /* Incoming client information, does not display it on console */
    if (sentence.startsWith(".hash, "))
    {
     SendThread.ack = true;
     sender.updateHash(sentence);
    }
    
    /* Incoming check for link status, send an ACK back */
    else if (sentence.equals(".alive?"))
    {
     String out = ".alive!";
                 
           byte buffer[] = new byte [1024];
           buffer = out.getBytes();
              InetAddress address = receivePacket.getAddress();
              DatagramPacket ack = new DatagramPacket(buffer, buffer.length, address, receivePacket.getPort());
                  
              clientSocket.send(ack);
    }
      
    /* Server ACKs when received a request to dereg, set ack to true */
    else if (sentence.equals("[Anda Offline. Bye.]"))
    {
     SendThread.ack = true;
     System.out.println(sentence);
     System.out.print(">>> ");
    }
    
    /* Server ACK */
    else if (sentence.equals("[Pesan diterima oleh server dan disimpan]"))
    {
     SendThread.ack = true;
     System.out.println(sentence); 
     System.out.print(">>> ");
    }
      
    /* Receives a regular message, ACKs back */
    else if (!sentence.startsWith("[Pesan yang diterima oleh "))
             {
              System.out.println(sentence);
              System.out.print(">>> ");
           String out = "[Pesan yang diterima oleh " + SendThread.hostname +".]";
                  
           byte buffer[] = new byte [1024];
           buffer = out.getBytes();
              InetAddress address = receivePacket.getAddress();
              DatagramPacket ack = new DatagramPacket(buffer, buffer.length, address, receivePacket.getPort());
                  
              clientSocket.send(ack);
             }

    /* Receives an ACK, print it, and continue */
    else
    {
     SendThread.ack = true;
     System.out.print(">>> ");
     System.out.println(sentence); 
     System.out.print(">>> ");
    }
   

  }
 }
 
 } 

SendThread.java
import java.io.*;
import java.net.*;
import java.util.*;

public class SendThread implements Runnable
{
    public static String hostname = null;
    public static String toname = null;
    public static DatagramSocket sock;
    static HashMap> hm = new HashMap>();
    static InetAddress serverIP = null;
    static int serverPort = -1;
    static int myPort = -1;
    static boolean online = false;
    static boolean ack = false;
    static int counter = 0;
    static String timeoutmode = null;
    static String buffer = null;

    /**
     * Constructor that initializes the variables and registers the client with the server
     * @param socket - client socket
     * @param host - name of client
     * @param serverIP - server's IP
     * @param serverPort - server's Port
     * @param myPort - client's port
     */
    public SendThread(DatagramSocket socket, String host, InetAddress serverIP, int serverPort, int myPort) 
    {
        sock = socket;

        SendThread.myPort = myPort;
        
        hostname = host;
        
        SendThread.serverIP = serverIP;
        
        SendThread.serverPort = serverPort;
 
        try 
        {
   register();
   
  } 
        catch (InterruptedException e) 
        {
   e.printStackTrace();
  }
        
    }

    /**
     * Send's main thread that takes any user input, parse the commands and apply necessary actions
     */
    public void run() 
    {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        while (true) 
        {
         /* Makes sure ack is received to prevent interruption of console input by receive thread */
         if (ack)
         {
          /* ACK counter resets to 0 */
          counter = 0;
          try 
          {
           
           String line = in.readLine();
           
           /* Parse commands only if online or if user tries to reg or exit after dereg */
           if (online || line.startsWith("reg") || line.startsWith("ctrl + c"))
           {
            /* If user wants to send */
            if (line.startsWith("send"))
            {
             if (line.split(" ")[1].equals(hostname))
             {
              System.out.println(">>> [Tidak bisa mengirim pesan sendiri!!!]");
              System.out.print(">>> ");
             }
             else
             {
              ack = false; 
              try
                 {
               sock.send(clientLookUp(line));
                 }
              catch (ArrayIndexOutOfBoundsException e)
              {
               ack = true;
               System.out.println(">>> [Tolong masukan clientname]");
               System.out.print(">>> ");
              }
              catch (StringIndexOutOfBoundsException e)
              {
               ack = true;
               System.out.println(">>> [Tolong masukan pesan]");
               System.out.print(">>> ");
              }
              catch (NullPointerException e)
              {
               ack = true;
               System.out.println(">>> [Klien tidak ditemukan, ketik table untuk melihat client yang tersedia (s).]");
               System.out.print(">>> ");
              } 
             }
            }
  
            /* table will show current clients, contact list equivalent */
            else if (line.equals("table"))
            {
          System.out.println(">>> Table klien yang online");
        Iterator iterator = hm.keySet().iterator(); 
        while (iterator.hasNext())
       {
        String value = hm.get(iterator.next().toString()).toString();  
        String output = value.substring(1, value.length()-1);        
        System.out.println(">>> " + output);  
       }
        System.out.print(">>> ");
            }
            
            /* dereg will log the client out, changing the status in the table */
            else if (line.startsWith("dereg"))
            {
             if (!online)
             {
              System.out.println(">>> [Anda sedang offline.]");
             }
             else
             {
              System.out.print(">>> ");
              deregister();
              online = false;
             }
             
            }
            
            /* allows user to reg back online */
            else if (line.startsWith("reg"))
            {
             if (online)
              System.out.println(">>> [Anda sedang online.]");
             else
             {
              System.out.print(">>> ");
              String[] values = line.split(" ");
              try
              {
               hostname = values[1];
               register();
               online = true;
              }
              catch (ArrayIndexOutOfBoundsException e)
              {
               System.out.println("[Tolong masukan clientname...]");
               System.out.print(">>> ");
              }
              
             }
            }
            
            /* dereg then exit program entirely */
            else if (line.equals("ctrl + c"))
            {
             if (online)
             {
              deregister();
             }
             System.out.print(">>> ");
             
             Thread.sleep(500); //Wait for ACK
             
             System.out.println("[Keluar]");
             System.exit(0);
            }
            
            else
            {
             System.out.println(">>> [Perintah tidak diakui, silakan coba lagi.]");
             System.out.print(">>> ");
            }

           }
 
           /* Refuses command while offline */
     else
     {
      System.out.println(">>> [Kamu sedang offline.]");
      System.out.println(">>> [Silakan Daftar atau keluar dari aplikasi.]");
      System.out.print(">>> ");
     }
    } 
          
          catch (Exception e) 
          {
     e.printStackTrace();
    }
         }
         
         /* Timeout for both server and client connections */
         else
         {
          if (timeoutmode.equals("server"))
           serverACK();
          else
           clientACK();
         }
        }
    }

    /**
     * Updates the local client hashmap
     * @param sentence - incoming info from server
     */
 public void updateHash (String sentence)
 {
  String[] values = sentence.split(", ");
  
  ArrayList list = new ArrayList();
  
  for (int i = 1; i < values.length; i++)
  {
   list.add (values[i]);
  }
  
  hm.put(values[1], list);
  
  list = new ArrayList(); 
 }
    
 /**
  * Searches through the local table and create a datagramPacket to client
  * If destination is unreachable, create a datagramPacket to server instead
  * @param input - user input
  * @return DatagramPacket to be sent
  */
 private static DatagramPacket clientLookUp(String input)
 {
  
  String[] list = input.split(" ");  
  String client = list[1];
  toname = client;
  //6 is the length of "send " and an additional " " after the client name
  int index = 6 + list[1].length();
  
  String message = hostname + ": " + input.substring(index);


  ArrayList values = hm.get(client);
  
  String ip = (String) values.get(1);
  ip = ip.substring(1);
  
  String status = (String) values.get(3);

  /* check local table first */
  if (status.equalsIgnoreCase("on"))
  {
   timeoutmode = "client";
   
   //Get the ip of current key
   InetAddress clientIP = null;

   try 
   {
    clientIP = InetAddress.getByName(ip);
   } 
   catch (UnknownHostException e) 
   {
    e.printStackTrace();
   } 
   
   //get the port of the current key
   int clientPort = Integer.parseInt((String) values.get(2)); 
   //get status

   byte[] sendData  = new byte[1024];  
   sendData = message.getBytes(); 
   buffer = ".off " + client + " " + hostname + " " + input.substring(index);
   
   DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, clientIP, clientPort); 

   return sendPacket;
  }
  
  /* if off, initiate offline chat */
  else
  {
   timeoutmode = "server";
   
   System.out.println(">>> [" + client + " offline, pesan dikirim ke server.]");
   System.out.print(">>> ");
   
   message = ".off " + client + " " + hostname + " " + input.substring(index);
   byte[] sendData  = new byte[1024]; 
   
   sendData = message.getBytes();  
   DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverIP, serverPort); 
 
   return sendPacket;

  }
 }
    
 /**
  * Registers client with server
  * @throws InterruptedException 
  */
 public void register() throws InterruptedException
 {
  
  /* Sends current host information */
        String sentence = ".register " + hostname + " " + myPort + " " + "on";
        
        byte[] sendData = new byte[1024];
  sendData = sentence.getBytes();
   
  DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverIP, serverPort); 
  
  try 
  {
   ack = false;   
   timeoutmode = "server";
   sock.send(sendPacket);
  } 
  catch (IOException e) 
  {
   e.printStackTrace();
  }
  
  online = true;
  
 }
 
 /**
  * Deregisters client from server
  * @throws SocketException 
  */
 private static void deregister() throws SocketException
 {
  /* Sends current host information */
        String sentence = ".deregister " + hostname + " " + myPort + " " + "off";
        
        byte[] sendData = new byte[1024];
  sendData = sentence.getBytes();
   
  DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverIP, serverPort); 
  
  try 
  {
   ack = false;
   timeoutmode = "server";
   sock.send(sendPacket);
  } 
  catch (IOException e) 
  {
   e.printStackTrace();
  }

  
  online = false;
 }
   
 /**
  * Puts thread to sleep for 500msec, retries for 5 times. If no ack is received
  * then it means server is not responding, quit gracefully.
  */
 private static void serverACK()
 {
  if (counter < 5)
  {
   try 
   {
    Thread.sleep(500);
   } 
   catch (InterruptedException e) 
   {
    e.printStackTrace();
   }
   counter++;
  }
  else
  {
   System.out.println("[Server tidak menanggapi]");
   System.out.println(">>> [Keluar]");
   System.exit(0);
  }
 }
 
 /**
  * Puts thread to sleep for 500msec, if still no ack, then destination client
  * is down, and redirect packet to server.
  */
 private static void clientACK()
 {
  if (counter < 1)
  {
   try 
   {
    Thread.sleep(500);
   } 
   catch (InterruptedException e) 
   {
    e.printStackTrace();
   }
   counter++;
  }
  else
  {
   System.out.println(">>> [Tidak ada ACK dari " + toname + ", pesan dikirim ke server.]");
   System.out.print (">>> ");
   
   byte[] sendData  = new byte[1024];
   sendData = buffer.getBytes();
   
   DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverIP, serverPort); 
 
   try 
   {
    ack = false;
    timeoutmode = "server";
    sock.send(sendPacket);
   } 
   catch (IOException e) 
   {
    e.printStackTrace();
   }
  }
 } 
}

UdpChat.java
import java.net.InetAddress;

/**
 * Provides a main method and parses arguments to initiate the appropriate mode
 *
 */
public class UdpChat 
{
 public static void main(String[] args) throws Exception 
 {
  
  try
  {
   String mode = null;
   mode = args[0].substring(1);

   /* Initiates the Server mode */
   if (mode.equals("s"))
   {
    int port = Integer.parseInt(args[1]);
    
    if (port < 1024)
    {
     System.out.println(">>> [Port server tidak bisa lebih kecil dari 1024]");
     System.exit(0);
    }
    if (port > 65535)
    {
     System.out.println(">>> [Port server tidak bisa lebih dari 65.535]");
     System.exit(0);
    }
    
    UDPServer newServer = new UDPServer(port); 
   }
   
   /* Initiates the Client Mode */
   else if (mode.equals("c"))
   {
    String hostname = args[1];
    InetAddress serverIP = InetAddress.getByName(args[2]);
    int serverPort = Integer.parseInt(args[3]);
    int clientPort = Integer.parseInt(args[4]);
    
    if (serverPort < 1024)
    {
     System.out.println(">>> [Port server tidak bisa lebih kecil dari 1024]");
     System.exit(0);
    }
    if (serverPort > 65535)
    {
     System.out.println(">>> [Server port " + serverPort + " tidak ada!]");
     System.exit(0);
    } 
    if (clientPort < 1024)
    {
     System.out.println(">>> [Port klien tidak bisa lebih kecil dari 1024]");
     System.exit(0);
    }
    if (clientPort > 65535)
    {
     System.out.println(">>> [Port " + serverPort + " tidak ada!]");
     System.exit(0);
    }

    UDPClient newClient = new UDPClient (hostname, serverIP, serverPort, clientPort); 
   }
   
   else
   {
    System.out.println(">>> [Tolong masukkan argumen yang benar.]");
   }
  }
  
  catch (ArrayIndexOutOfBoundsException e)
  {
   System.out.println(">>> [Tolong masukkan argumen yang benar.]");
  }
 }
}

Kelompok:
Asri Ansar (08052931)
Tangguh Sanjaya (08052932)
Dodo Suratmo (08052950) 
Nova Tri Cahyono (091051014)
Cukamnoto Hariyadi (121052129)
Wintoko (121053085)




emoticon Tolong dibaca terlebih dahulu !

Anda sedang membaca artikel tentang Aplikasi Chatting dengan Java berbasis Command Line dan anda bisa menemukan artikel Aplikasi Chatting dengan Java berbasis Command Line ini dengan url https://www.nova13.com/2012/11/aplikasi-chatting-java.html, Anda boleh menyebar luaskannya atau mengcopy paste-nya jika artikel Aplikasi Chatting dengan Java berbasis Command Line ini sangat bermanfaat bagi teman-teman Anda, namun jangan lupa untuk meletakkan link postingan Aplikasi Chatting dengan Java berbasis Command Line sebagai sumbernya.

If you Like this, please share it?

Ping your blog, website, or RSS feed for Free

Related Post:



Translates