Search code examples
javachatsocketserver

Why cant both my client communicate to each other? (java server socket)


i'm having trouble to connect TWO clients. is it bcoz i am using DataOutputStream and DataInputStream instead of BufferedReader and PrintWritter? For some reason, it just dont connect to each other even if i set the server sockets and sockets to be interconnected through localhost and port 8000.

i could not send messages between these two clients. But, yes, they can connect to the server. However, I want my clients to communicate each other instead so that it works like an online chat.

Server Side:

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

import javax.swing.*;

public class Server extends JFrame {
// Text area for displaying contents
private static JTextArea jta = new JTextArea();


public static void main(String[] args) {
    new Server();
}

public Server() {

    setLayout(new BorderLayout());
    add(new JScrollPane(jta), BorderLayout.CENTER);

    setTitle("Server");
    setSize(500, 300);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true); // It is necessary to show the frame here!

    // Place text area on the frame
    try {
    // Create a server socket
    ServerSocket serverSocket = new ServerSocket(8000);
    jta.append("Server started at " + new Date() + '\n');
    try {
        while (true) {
            new Handler(serverSocket.accept()).start();
        }
    } finally {
        serverSocket.close();
    }

}
catch(IOException ex) {
    System.err.println(ex);
    }
}

public static class Handler extends Thread{

    Socket socket;
    DataInputStream inputFromClient;
    DataOutputStream outputToClient;

    public Handler(Socket socket){
        this.socket = socket;
    }

    public void run(){
        // Listen for a connection request
          //Socket socket = serverSocket.accept();
          try{
        // Create data input and output streams
           inputFromClient = new DataInputStream(socket.getInputStream());
           outputToClient = new DataOutputStream(socket.getOutputStream());

            while (true) {

            // Receive data from the client
            String message =inputFromClient.readUTF();

            System.out.println("Server: Receive input");

            jta.append("Word received from client: " + message + '\n');


            // DO converting process
            //String newMessage ="";
            //newMessage= message.toUpperCase();
            // Send data back to the client
            outputToClient.writeUTF(message);
            //jta.append("Word Converted: " + newMessage + '\n');

            }
          }catch(IOException ex) {
            System.err.println(ex);
            }
        } 
    }
}

Client side

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

public class Client extends JFrame {
// Text field for receiving data
private JTextField jtf = new JTextField();
// Text area to display contents
private JTextArea jta = new JTextArea();
// IO streams
private  DataOutputStream toServer;
private  DataInputStream fromServer;

public static void main(String[] args) {
    new Client();
}

public Client() {
// Panel p to hold the label and text field
    JPanel p = new JPanel();
    p.setLayout(new BorderLayout());
    p.add(new JLabel("Enter word: "), BorderLayout.WEST);
    p.add(jtf, BorderLayout.CENTER);
    jtf.setHorizontalAlignment(JTextField.RIGHT);

    setLayout(new BorderLayout());
    add(p, BorderLayout.NORTH);
    add(new JScrollPane(jta), BorderLayout.CENTER);

    jtf.addActionListener(new Listener()); // Register listener

    setTitle("Client");
    setSize(500, 300);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true); // It is necessary to show the frame here!

    try {
    // Create a socket to connect to the server
     Socket socket = new Socket("localhost", 8000);
          // Socket socket = new Socket("130.254.204.36", 8000);
          // Socket socket = new Socket("drake.Armstrong.edu", 8000);

      // Create an input stream to receive data from the server
      fromServer = new DataInputStream(
        socket.getInputStream());

      // Create an output stream to send data to the server
      toServer =
        new DataOutputStream(socket.getOutputStream());


    }
    catch (IOException ex) {
    jta.append(ex.toString() + '\n');
    }
}

private class Listener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        try {
        // Get the data from the text field
        String message = (jtf.getText().trim());

        // Send the data to the server
         toServer.writeUTF(message);

        // Get data from the server
         String serverMessage = fromServer.readUTF();
         System.out.println("from server");

        // Display to the text area

        jta.append("Word is " + message + "\n");
        jta.append("Word received from the server is "
          + serverMessage + '\n');
        toServer.flush();

        }
        catch (IOException ex) {
        System.err.println(ex);
        }
    }
}
}

Solution

  • Your software is not designed to handle client to client communication.

    To achieve this you would have to:

    • store your client Handlers on the server (not throwing them away; use something dynamic like a LinkedList)
    • add a method to the Handler that allows to sent arbitrary messages to the Client this Handler represents
    • receive the client messages in a Handler
      • pass them to the server
      • send the message to the clients in the list using the sending method

    I'm kind of 1999 "I can only show you the door. You're the one that has to walk through it." but SO seems to see this different today. So here we go.

    Server:

    import java.io.*;
    import java.net.*;
    import java.util.*;
    import java.awt.*;
    
    import javax.swing.*;
    
    public class Server extends JFrame {
    // Text area for displaying contents
    private static JTextArea jta = new JTextArea();
    LinkedList<Handler> handlers = new LinkedList<Handler>();
    
    public static void main(String[] args) {
        new Server();
    }
    
    public void sendmessagetoall(String message)
    {
        for(Handler current : handlers)
        {
            try
            {
                current.writeMessage(message);
            }
            catch (IOException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    public Server() {
    
        setLayout(new BorderLayout());
        add(new JScrollPane(jta), BorderLayout.CENTER);
    
        setTitle("Server");
        setSize(500, 300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true); // It is necessary to show the frame here!
    
        // Place text area on the frame
        try {
        // Create a server socket
        ServerSocket serverSocket = new ServerSocket(8000);
        jta.append("Server started at " + new Date() + '\n');
        try {
            while (true) {
                Handler noob =  new Handler(serverSocket.accept(),this);
                handlers.add(noob);
                noob.start();
            }
        } finally {
            serverSocket.close();
        }
    
    }
    catch(IOException ex) {
        System.err.println(ex);
        }
    }
    
    public static class Handler extends Thread{
    
        Socket socket;
        Server parent;
        DataInputStream inputFromClient;
        DataOutputStream outputToClient;
    
        public Handler(Socket socket, Server parent){
            this.socket = socket;
            this.parent = parent;
        }
    
        public void writeMessage(String message) throws IOException
        {
            outputToClient.writeUTF(message);
        }
    
        public void run(){
            // Listen for a connection request
              //Socket socket = serverSocket.accept();
              try{
            // Create data input and output streams
               inputFromClient = new DataInputStream(socket.getInputStream());
               outputToClient = new DataOutputStream(socket.getOutputStream());
    
                while (true) {
    
                // Receive data from the client
                String message =inputFromClient.readUTF();
    
                System.out.println("Server: Receive input");
    
                jta.append("Word received from client: " + message + '\n');
    
    
                // DO converting process
                //String newMessage ="";
                //newMessage= message.toUpperCase();
                // Send data back to the client
                //writeMessage(message);
                parent.sendmessagetoall(message);
                //jta.append("Word Converted: " + newMessage + '\n');
    
                }
              }catch(IOException ex) {
                System.err.println(ex);
                }
            } 
        }
    }
    

    Client:

    import java.io.*;
    import java.net.*;
    import java.awt.*;
    import java.awt.event.*;
    
    import javax.swing.*;
    
    public class Client extends JFrame {
    // Text field for receiving data
    private JTextField jtf = new JTextField();
    // Text area to display contents
    private JTextArea jta = new JTextArea();
    // IO streams
    private  DataOutputStream toServer;
    private  DataInputStream fromServer;
    
    public static void main(String[] args) {
        new Client();
    }
    
    public Client() {
    // Panel p to hold the label and text field
        JPanel p = new JPanel();
        p.setLayout(new BorderLayout());
        p.add(new JLabel("Enter word: "), BorderLayout.WEST);
        p.add(jtf, BorderLayout.CENTER);
        jtf.setHorizontalAlignment(JTextField.RIGHT);
    
        setLayout(new BorderLayout());
        add(p, BorderLayout.NORTH);
        add(new JScrollPane(jta), BorderLayout.CENTER);
    
        jtf.addActionListener(new Listener()); // Register listener
    
        setTitle("Client");
        setSize(500, 300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true); // It is necessary to show the frame here!
    
        try {
        // Create a socket to connect to the server
         Socket socket = new Socket("localhost", 8000);
              // Socket socket = new Socket("130.254.204.36", 8000);
              // Socket socket = new Socket("drake.Armstrong.edu", 8000);
    
          // Create an input stream to receive data from the server
          fromServer = new DataInputStream(
            socket.getInputStream());
    
          // Create an output stream to send data to the server
          toServer =
            new DataOutputStream(socket.getOutputStream());
    
          new Thread(new Runnable(){
    
            @Override
            public void run()
            {
                while(true)
                {
                    String serverMessage = "";
                    try
                    {
                        serverMessage = fromServer.readUTF();
                    }
                    catch (IOException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    jta.append("Word received from the server is "
                              + serverMessage + '\n');
                }
    
            }})
            .start();
    
    
        }
        catch (IOException ex) {
        jta.append(ex.toString() + '\n');
        }
    }
    
    private class Listener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            try {
            // Get the data from the text field
            String message = (jtf.getText().trim());
    
            // Send the data to the server
             toServer.writeUTF(message);
    
            // Get data from the server
    
             System.out.println("from server");
    
            // Display to the text area
    
            jta.append("Word is " + message + "\n");
    
            toServer.flush();
    
            }
            catch (IOException ex) {
            System.err.println(ex);
            }
        }
    }
    }
    

    A quick and dirty edit to your code.
    This doesn't handle Clients that dropped their connection and distributes the message to all clients, but you should get a starting point.