0

I have a client and server class, the client has GUI. If I open the server and then the client, everything is ok. But If I open the server and two clients, the clients don't messaging each other, only messaging with server like echo client. I guess I'm jumping some details in my code, but I can't figure out where I wrong.

enter image description here

CLIENT

package program;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

    public class gui
    {
        private Socket socket        = null;
        private DataInputStream input = null;
        private DataOutputStream out     = null;
        public String data = "0";

        server _server;
        JFrame pencere;
        JButton button;
        JTextArea area;
        JTextField type;
        public gui(){


            try
            {
                socket = new Socket("127.0.0.1",4000);
                System.out.println("Connected");

                // takes input from terminal
                input = new DataInputStream(socket.getInputStream());

                // sends output to the socket
                out = new DataOutputStream(socket.getOutputStream());
            }
            catch(UnknownHostException u)
            {
                System.out.println(u);
            }
            catch(IOException i)
            {
                System.out.println(i);
            }



            pencere = new JFrame("oxChat");
            pencere.setSize(640,480);
            pencere.setLayout(null);
            button = new JButton("gönder");
            button.addActionListener( new ActionListener()
            {
                @Override
                public void actionPerformed(ActionEvent e)
                {
                    try {
                        out.writeUTF(type.getText());
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            });
            area = new JTextArea();
            type = new JTextField();
            pencere.add(type);
            pencere.add(area);
            pencere.add(button);
            area.setBounds(0,0,640,350);
            type.setBounds(0,370,640,25);
            button.setBounds(640/2-80/2,400,80,30);
            pencere.setVisible(true);
            pencere.setResizable(false);
            pencere.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            new Thread (new dagitici(socket,this)).start();
        }

        public static void main(String[] args) throws IOException {
            gui app = new gui();
        }

        String getData(){
            return data;
        }
        void setData(String dataa){
            this.data = dataa;
            area.append(this.data+"\n");
        }

    }

    class dagitici extends Thread{
        private Socket socket        = null;
        private DataInputStream input = null;
        private DataOutputStream out     = null;
        gui g;
        public String okunan="";
        public dagitici(Socket socket,gui g){
            this.socket = socket;
            this.g = g;
        }
        @Override
        public void run() {

            try {
                input = new DataInputStream(socket.getInputStream());
                out = new DataOutputStream(socket.getOutputStream());
            } catch (IOException e) {
                e.printStackTrace();
            }

            while(true){
                try {
                    System.out.println("a");
                    okunan=input.readUTF();
                    g.setData(okunan);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

SERVER

package program;

// A Java program for a Server
import com.sun.jdi.PathSearchingVirtualMachine;

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

public class server
{
    private Socket socket;
    private ServerSocket server;
    public static   String data;
    // constructor with port
    public void start(int port){
        try {
            server = new ServerSocket(port);
            while(true){
                socket = server.accept();
                new Thread (new ConnectionHandler(socket)).start();
            }
        }catch(IOException i){

        }
    }

    public static void main(String[] args) {
        server _server = new server();
        _server.start(4000);
    }
}

class ConnectionHandler extends Thread{
    gui app;
    private String data;
    private Socket       socket = null;
    private DataInputStream in   = null;
    private DataOutputStream out     = null;
    public ConnectionHandler(Socket socket){
        this.socket=socket;
    }
    @Override
    public void run() {
        try
        {
            System.out.println("Waiting for a client ...");
            System.out.println("Client accepted");
            in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
            out = new DataOutputStream(socket.getOutputStream());

            String line = "";

            // reads message from client until "Over" is sent
            while (!line.equals("Over"))
            {
                try
                {
                    line = in.readUTF();
                    out.writeUTF(line);
                }
                catch(IOException i)
                {
                    System.out.println(i);
                }
            }
            System.out.println("Closing connection");

            // close connection
            socket.close();
            in.close();
        }
        catch(IOException i)
        {
            System.out.println(i);
        }
    }
    public String getServerData(){
        return  data;
    }
}
2
  • Did you read my answer to your last question? I already explained how to do that. In this code you only send the data back on the same socket it comes from. Commented Oct 29, 2019 at 17:14
  • I'm thinking to make for loop to send data through sockets. line = in.readUTF(); for(int a=0;a<threads.length-1;a++){ PrintStream os = new PrintStream(threads[a].getSocket().getOutputStream()); out.writeUTF(line); } But how can I find socket of any thread ? getSocket() won't work. Commented Oct 29, 2019 at 17:30

1 Answer 1

2
  • Add a List<ConnectionHandler> to your server class:

    List<ConnectionHandler> clients = new ArrayList<>();
    
  • And for good measure, a lock:

    Object lock = new Object();
    
  • Then we need to add any new connected client to that list:

    socket = server.accept();
    ConnectionHandler client = new ConnectionHandler(this, socket)
    synchronized (lock) {
        clients.add(client);
    }
    new Thread(client).start();
    
  • Now we just need a method to distribute all the incoming messages in the server class:

    void distributeMessage(String message) {
        List<ConnectionHandler> clientsCopy;
        synchronized (lock) {
            clientsCopy = new ArrayList<>(clients);
        }
        for (ConnectionHandler client : clientsCopy) {
            client.sendMessage(message);
        }
    }
    
  • Now we need to change the ConnectionHandler, and we start by cleaning up the fields:

    private Socket socket;
    private DataInputStream in;
    private DataOutputStream out;
    private server server;
    

    Those are all the fields that we need.

  • Next we need to change the constructor of this class:

    public ConnectionHandler(server server, Socket socket) {
        this.server = server;
        this.socket = socket;
        this.in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        this.out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
    }
    

    All fields should be initialized in the constructor if possible.

  • Then we have to add our new sendMessage(String message) method:

    public void sendMessage(String message) {
        try {
            out.writeUTF(message);
            out.flush();
        } catch (IOException e) {
            // TODO: Here you HAVE to check if the connection was closed
            // And if it was closed, call a method in the server class to
            // remove this client.
            e.printStackTrace();
        }
    }
    
Sign up to request clarification or add additional context in comments.

1 Comment

List<ConnectionHandler> clients = new ArrayList<>(); solved my problem thanks !

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.