Open In App

A Group Chat Application in Java

Last Updated : 27 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

In this post, a group chat application using MulticastSocket (Java Platform SE 7) class is discussed. A MulticastSocket is a (UDP) DatagramSocket, with additional capabilities for joining "groups" of other multicast hosts on the internet.

Implementation

Java
import java.net.*; 
import java.io.*; 
import java.util.*; 
public class GroupChat 
{ 
    private static final String TERMINATE = "Exit"; 
    static String name; 
    static volatile boolean finished = false; 
    public static void main(String[] args) 
    { 
        if (args.length != 2) 
            System.out.println("Two arguments required: <multicast-host> <port-number>"); 
        else
        { 
            // CHANGES HAVE BEEN DONE HERE: Added validation for multicast address and port
            try
            { 
                InetAddress group = InetAddress.getByName(args[0]); 
                if (!group.isMulticastAddress()) {
                    System.out.println("Error: Invalid multicast address");
                    return;
                }
                
                int port = Integer.parseInt(args[1]); 
                if (port < 1024 || port > 65535) {
                    System.out.println("Error: Port number must be between 1024 and 65535");
                    return;
                }
                
                Scanner sc = new Scanner(System.in); 
                System.out.print("Enter your name: "); 
                name = sc.nextLine(); 
                
                MulticastSocket socket = new MulticastSocket(port); 
              
                // CHANGES HAVE BEEN DONE HERE: Set proper TTL value
                socket.setTimeToLive(1); // Changed from 0 to 1 for local subnet
                  
                socket.joinGroup(group); 
                Thread t = new Thread(new ReadThread(socket,group,port)); 
                t.start();  
                  
                System.out.println("Start typing messages...\n"); 
                try {
                    while(true) 
                    { 
                        String message = sc.nextLine(); 
                        if(message.equalsIgnoreCase(GroupChat.TERMINATE)) 
                        { 
                            finished = true; 
                            // CHANGES HAVE BEEN DONE HERE: Proper cleanup
                            socket.leaveGroup(group); 
                            socket.close(); 
                            sc.close(); // Added scanner close
                            break; 
                        } 
                        message = name + ": " + message; 
                        byte[] buffer = message.getBytes(); 
                        DatagramPacket datagram = new DatagramPacket(buffer,buffer.length,group,port); 
                        socket.send(datagram); 
                    } 
                } finally {
                    if (!socket.isClosed()) {
                        socket.leaveGroup(group);
                        socket.close();
                    }
                    sc.close();
                }
            } 
            catch(UnknownHostException uhe) {
                System.out.println("Error: Invalid multicast host");
                uhe.printStackTrace();
            }
            catch(NumberFormatException nfe) {
                System.out.println("Error: Port must be a number");
                nfe.printStackTrace();
            }
            catch(SocketException se) 
            { 
                System.out.println("Error creating socket"); 
                se.printStackTrace(); 
            } 
            catch(IOException ie) 
            { 
                System.out.println("Error reading/writing from/to socket"); 
                ie.printStackTrace(); 
            } 
        } 
    } 
} 

class ReadThread implements Runnable 
{ 
    private final MulticastSocket socket; // CHANGES HAVE BEEN DONE HERE: Made final
    private final InetAddress group; 
    private final int port; 
    private static final int MAX_LEN = 1000; 
    
    ReadThread(MulticastSocket socket, InetAddress group, int port) 
    { 
        this.socket = socket; 
        this.group = group; 
        this.port = port; 
    } 
      
    @Override
    public void run() 
    { 
        while(!GroupChat.finished) 
        { 
            byte[] buffer = new byte[ReadThread.MAX_LEN]; 
            DatagramPacket datagram = new DatagramPacket(buffer, buffer.length, group, port); 
            try
            { 
                socket.receive(datagram); 
                String message = new String(buffer, 0, datagram.getLength(), "UTF-8"); 
                if(!message.startsWith(GroupChat.name)) 
                    System.out.println(message); 
            } 
            catch(SocketException se) {
                if (!GroupChat.finished) {
                    System.out.println("Socket error: " + se.getMessage());
                }
            }
            catch(IOException e) 
            { 
                if (!GroupChat.finished) {
                    System.out.println("Error reading message: " + e.getMessage());
                }
            } 
        } 
    } 
}

Save the file as GroupChat.java and compile it using javac and then run the program using two command line arguments as specified. A multicast host is specified by a class D IP address and by a standard UDP port number. Class D IP addresses are in the range 224.0.0.0 to 239.255.255.255, inclusive. The address 224.0.0.0 is reserved and should not be used. Here is a sample output of the above program:

multicast socket api in javamulticast socket api in java1multicast socket api in java12

We have used the multicast host IP address as 239.0.0.0 and the port number as 1234 (since the port numbers 0 through 1023 are reserved). There are 3 members in the group: Ironman, CaptainAmerica, and Groot. Start all three terminals first before sending the message, otherwise messages which are sent before starting the terminal are lost (since there is no facility of buffer incorporated to store the messages.) We need two threads in this application. One for accepting the user input (using the java.util.Scanner class) and the other for reading the messages sent from other clients. Hence I have separated the thread which does the reading work into ReadThreadclass. For leaving the group, any of the user can type in Exit to terminate the session. The above program is executed on a single machine. Socket programming is meant for distributed programming. The same piece of code snippet when present on different machines which have Java installed can satisfy that requirement. This is just the bare bones service logic. The project would be even more fascinating if the front-end is developed. You can use Java’s AWT (Abstract Window Toolkit) or its advanced counterpart, Java Swing to develop the front end. Since this wouldn’t be part of Socket programming I’m leaving it untouched without getting into the details.

Additional points:

  • You can incorporate network security feature by performing encryption before sending the message over the network.
  • Primitive techniques such as Caesar cipher or advanced methods such as RSA can be used to perform encryption-decryption. You can try using Java’s RMI (Remote Method Invocation) to perform the same task.
  • Here, you can leverage the abstraction offered by Java to maximum extent. However, if your primary objective is efficiency, then Socket programming is the best choice. Since it doesn’t require any run time support, it is a bit faster compared to RMI.

Next Article
Article Tags :
Practice Tags :

Similar Reads