0

I'm new to the concept of creating a server and multiple clients using Java, so apologies if this is an obvious fix. I've been trying to code a jframe chat program that has a server and two clients, which currently are all using the same port. Whatever data is sent by client one will be passed to the server, which will display it. So far, the code does this, however, I also want to pass said data to the other client. I'm trying to code the program so that I can specify the client the data is sent to.

The code follows as:

Server Code.

package Chats;

import java.io.*;
import java.net.*;

public class Chat_Server extends javax.swing.JFrame 
{
    static ServerSocket ss;
    static Socket s;
    static DataInputStream din;
    static DataOutputStream dout;

    public Chat_Server() 
    {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        Msg_Area = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        Msg_Area.setColumns(20);
        Msg_Area.setRows(5);
        jScrollPane1.setViewportView(Msg_Area);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(32, 32, 32)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 332, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(36, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(24, 24, 24)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 237, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(39, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    public static void main(String args[]) 
    {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Chat_Server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Chat_Server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Chat_Server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Chat_Server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        java.awt.EventQueue.invokeLater(new Runnable() 
        {
            public void run() 
            {
                new Chat_Server().setVisible(true);
            }
        });

        String msgin = "";
        try
        {
            ss = new ServerSocket(1201); // Server starts at 1201 port number
            s = ss.accept(); // Now server will accept the connections.
            din = new DataInputStream(s.getInputStream());
            dout = new DataOutputStream(s.getOutputStream());

            while(!msgin.equals("exit"))
            {
                msgin = din.readUTF();
                Msg_Area.setText(Msg_Area.getText().trim() + "\n Client: \t" + msgin); // Displaying the message from client  
            }
        }

        catch(Exception e)
        {

        }
    }

    // Variables declaration - do not modify                     
    private static javax.swing.JTextArea Msg_Area;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration                   
}

Client Code.

package Chats;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;

public class Chat_Client extends javax.swing.JFrame
{
    static Socket s;
    static DataInputStream din;
    static DataOutputStream dout;

    public Chat_Client() 
    {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        Msg_Text = new javax.swing.JTextField();
        jScrollPane1 = new javax.swing.JScrollPane();
        Msg_Area = new javax.swing.JTextArea();
        Msg_Send = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        Msg_Text.setText("jTextField1");

        Msg_Area.setColumns(20);
        Msg_Area.setRows(5);
        jScrollPane1.setViewportView(Msg_Area);

        Msg_Send.setText("jButton1");
        Msg_Send.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Msg_SendActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(29, 29, 29)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 332, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(Msg_Text, javax.swing.GroupLayout.PREFERRED_SIZE, 257, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 31, Short.MAX_VALUE)
                        .addComponent(Msg_Send)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGap(19, 19, 19)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 196, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 31, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(Msg_Text, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(Msg_Send))
                .addGap(23, 23, 23))
        );

        pack();
    }// </editor-fold>                        

    private void Msg_SendActionPerformed(java.awt.event.ActionEvent evt) {                                         
        try
        {
            String msgout = "";
            msgout = Msg_Text.getText().trim();
            dout.writeUTF(msgout);
        }

        catch (Exception e)
        {
            //handle exceptions here.
        }
    }                                        

    public static void main(String args[]) 
    {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Chat_Client.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Chat_Client.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Chat_Client.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Chat_Client.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        java.awt.EventQueue.invokeLater(new Runnable() 
        {
            public void run() 
            {
                new Chat_Client().setVisible(true);
            }
        });

        try
        {
            s = new Socket ("127.0.0.1", 1201); // Here the ip ddress is local address.
            din = new DataInputStream(s.getInputStream());
            dout = new DataOutputStream(s.getOutputStream());
            String msgin = "";

            while (!msgin.equals("exit"))
            {
                msgin = din.readUTF();
                Msg_Area.setText(Msg_Area.getText().trim() + "\n Server: \t" + msgin);
            }

        }

        catch(Exception e)
        {
            //Exception Code
        }    
    }

    // Variables declaration - do not modify                     
    private static javax.swing.JTextArea Msg_Area;
    private javax.swing.JButton Msg_Send;
    private javax.swing.JTextField Msg_Text;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration                   

}

I have another page set up for the other client but so far the code is a carbon copy of the first client page, so there's no point posting it.

1
  • Unless you want to learn nio (which offers a way to work in a single server thread) you will need to introduce threads into your server. Currently the server blocks on accept(), then establishes one connection, then blocks on read(). Each client should run in a unique Thread, so the main server can continue to accept() new connections. Further, you need to maintain a pool of active connections, to be able to write messages to multiple clients on demand. If you only have two clients, you can simplify this a little, but regardless will need multiple threads. Commented Apr 12, 2018 at 21:51

1 Answer 1

1

You're only accepting a single client with ss.accept() and that's it. ServerSocket#accept waits for a SINGLE incoming client connection and creates a Socket object. In order to accept multiple connections you need continuously loop ss.accept() to keep listening for other client connections. Once a new connection is made you can add it to a list. (I have not tested the code, it's more just to point you in the direction you need)

public static void main(String []args) throw Exception{
    ServerSocket serverSocket = new ServerSocket(1201);
    List<Socket> clients = new ArrayList<Socket>();

    while(true) {//continuously listening for a new connection
        Socket client = serverSocket.accept(); 
        clients.add(client); 
    }
} 

Now the problem with this is that if your server constantly listens for a connection it'll block your thread. So everytime a connection is added, spawn a new thread to handle it.

public static void main(String []args) throw Exception{
    ServerSocket serverSocket = new ServerSocket(1201);
    List<Socket> clients = new ArrayList<Socket>();

    while(true) {
        Socket client = serverSocket.accept();
        clients.add(client);
        new Thread(new Runnable(){
           public void run(){
              //Handle socket here
           }
        }).start();
    }
}

If you want to avoid creating multiple threads like this, then you're gonna have to use nio socketchannels.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much for the help. I really appreciate it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.