2

I ve created a simple MultiThreaded server. Everytime it accepts client a DataInputStream and DataOutputStream is created and the comunication start

Server:

public class Connection implements Runnable{
boolean isAlreadyOpened = false;

@Override
public void run() {
    // TODO Auto-generated method stub  
    try {           
        ServerSocket ss = new ServerSocket(7000);
        while(true){
            System.out.println("Il Server sta cercando Connessioni");
            Socket s = ss.accept();
            System.out.println("Il Server ha accettato un Client");

            Thread t2 = new Thread(new Runnable(){
                public void run(){             
                   try {

                        DataInputStream dis = new DataInputStream(s.getInputStream());
                        isAlreadyOpened = true;
                        DataOutputStream dos = new DataOutputStream(s.getOutputStream());
                        while(true){
                            String test = dis.readUTF();
                            dos.writeUTF(test);
                            System.out.println(test);
                            dos.flush();
                        }                       
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                        isAlreadyOpened = false;
                    }  
                }           
            });
            t2.start();
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
 }  
}

I ve tried to connect an Android application and a JavaApp; every 40 seconds both of these programs send a string via writeUTF. The connection is established correctly from both Clients but the server receives Data just from the last one that connects to server. How can I allow the server to receive/send the data from/to ALL the clients?

EDIT:

I ve tried to set this:

public class Connection implements Runnable {

 @Override
  public void run() {

    try {
        ServerSocket ss = new ServerSocket(7000);
        while (true) {
            System.out.println("Server is listening");
            Socket s = ss.accept();
            System.out.println("Client Accepted");

            Thread t2 = new Thread(new Runnable() {
                public void run() {
                    try {
                        DataInputStream dis = new DataInputStream(s.getInputStream());
                        DataOutputStream dos = new DataOutputStream(s.getOutputStream());
                        while (true) {
                            String test = dis.readUTF();
                            dos.writeUTF(test);
                            System.out.println(test);
                            dos.flush();
                        }
                    } catch (IOException 
                        e.printStackTrace();
                    } finally {
                        try {
                            s.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });                 
    t2.start();
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

But the result is the same

EDIT:

Andorid Client Code

public class Connection implements Runnable {
@Override
public void run() {
    try {
        Socket s = new Socket("127.0.0.1", 7000);
        DataInputStream dis = new DataInputStream(s.getInputStream());
        DataOutputStream dos = new DataOutputStream(s.getOutputStream());

        while(true){
           dos.writeUTF("FromAndroid");
            Log.d("InputStreammmm", dis.readUTF());
         Thread.sleep(10000)
        }

    } catch (IOException e) {
        e.printStackTrace();
    }

}

JAVA APP CLIENT CODE

@Override
public void run() {
     try {

        Socket socket = new Socket("127.0.0.1", 7000);
        System.out.println("Connessooo");
         DataInputStream dis = new DataInputStream(socket.getInputStream());
         DataOutputStream dos = new DataOutputStream(socket.getOutputStream());

         while(true){
         dos.writeUTF("Invioooooooooooooooooooooooooo");
         result = dis.readUTF();
         System.out.println(result);
         Thread.sleep(10000);
         }

    } catch (IOException e) {

        e.printStackTrace();
    } catch (InterruptedException e) {

        e.printStackTrace();
    }
}

EDIT WITH LIST OF SOCKET:

public class Connection implements Runnable {
List<Socket> sList = new ArrayList<>();
Socket s;
int i = 0;

@Override
public void run() {
    // TODO Auto-generated method stub
    try {
        ServerSocket ss = new ServerSocket(7000);
        while (true) {
            System.out.println("Server Listening");
            s = ss.accept();
            sList.add(s);

            System.out.println("Accepted Client --- " +s.toString());
            Thread t2 = new Thread(new Runnable() {
                public void run() {
                    try {
                        DataInputStream dis = new DataInputStream(s.getInputStream());  

                        while (true) 
                        {
                            String test = dis.readUTF();
                            System.out.println("Message sent from -- " + sList.get(i).toString());
                            System.out.println(test);

                            while(i < sList.size()){
                                 DataOutputStream dos = new DataOutputStream(sList.get(i).getOutputStream());
                                 dos.writeUTF(test);    
                                 System.out.println("Message Sent to -- " + sList.get(i).toString());
                                 dos.flush();
                                 ++i;
                             }
                            i=0;
                        }
                    } catch (IOException e) 
                    {
                        e.printStackTrace();
                    } finally
                    {
                        try
                        {                      
                            System.out.println("Closing Socket --- " + sList.get(i).toString());
                            sList.get(i).close();
                            sList.remove(i);

                        }
                        catch (IOException e)
                        {
                            e.printStackTrace();
                        }
                    }
                }
            });
            t2.start();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

}

Doing in this way my problem is solved as suggested by EJP...

Alessio Trecani
  • 713
  • 2
  • 10
  • 25
  • 1
    You're never closing the accepted socket. But otherwise this code should work. Are you sure the problem isn't at the client end? But how does this code compile when `s` isn't final? – user207421 Feb 11 '16 at 22:14
  • What if the 3 clients connect quickly but don't immediately send data to the server. These variables all go out of scope. Of course this code is not OK. – peter.petrov Feb 11 '16 at 22:15
  • 1
    @peter.petrov The code will block in `readUTF()` until data is received or an exception occurs. Nothing wrong here. – user207421 Feb 11 '16 at 22:17
  • @EJP OK, but who keeps reference to `s` and `t2`? Aren't they subject to garbage collection almost immediately? Maybe I am wrong, I just read the code, didn't try anything. – peter.petrov Feb 11 '16 at 22:17
  • @EJP I m not closing the socket becasue the server should listen for data from clients.. ClientSide I never close the socket connection.. I simply have a writeutf called everyt tot seconds – Alessio Trecani Feb 11 '16 at 22:17
  • 1
    You must close the accepted socket `s` after the loop. The `isAlreadyOpened` variable is pointless: remove it. – user207421 Feb 11 '16 at 22:19
  • @peter.petrov There's a mystery about why `s` isn't final, but a socket won't be garbage-collected while there are references to it or its streams, and a thread won't be garbage-collected while it's running. – user207421 Feb 11 '16 at 22:20
  • @EJP I ve tried to put s.close() after dos.flush but it throws immediatly an exception "Socket is Closed".. I can post the Client code if it can help? – Alessio Trecani Feb 11 '16 at 22:25
  • 1
    Of course. That's not where I said to put it, but it should be closed in a `finally` block after the `catch`, actually. – user207421 Feb 11 '16 at 22:26
  • I ve tried also after "dos.flush}" ( I mean outside the while loop) but eclipse says Unreacheble code. I ve tried to declare the Socket outside the thread but it is the same result – Alessio Trecani Feb 11 '16 at 22:30
  • 1
    It should be closed in a `finally` block after the `catch`, actually. Not that I'm claiming it will solve your problem. There's no reason to declare the socket outside the thread. – user207421 Feb 11 '16 at 22:31
  • I ve updated the thread.. is that what you meant? – Alessio Trecani Feb 11 '16 at 22:35
  • 1
    Yes, but can you please format your code correctly? Very difficult to read like this. – user207421 Feb 11 '16 at 22:38
  • @peter.petrov OK thanks, well done, clears up that mystery. – user207421 Feb 11 '16 at 22:46
  • I ve tried to format it a little bit.. probably now is more readable – Alessio Trecani Feb 11 '16 at 22:47
  • @peter.petrov Can we please delete our irrelevant discussion? – user207421 Feb 11 '16 at 23:15

1 Answers1

1

Cannot reproduce.

Test program, copy-pasted from your edited code and added final to Socket s as I am using Java 7, and added client code:

public class Connection implements Runnable
{

    @Override
    public void run()
    {

        try
        {
            ServerSocket ss = new ServerSocket(7000);
            while (true)
            {
                System.out.println("Server is listening");
                final Socket s = ss.accept();
                System.out.println("Client Accepted");

                Thread t2 = new Thread(new Runnable()
                {
                    public void run()
                    {
                        try
                        {
                            DataInputStream dis = new DataInputStream(s.getInputStream());
                            DataOutputStream dos = new DataOutputStream(s.getOutputStream());
                            while (true)
                            {
                                String test = dis.readUTF();
                                dos.writeUTF(test);
                                System.out.println(test);
                                dos.flush();
                            }
                        }
                        catch (IOException e)
                        {
                            e.printStackTrace();
                        }
                        finally
                        {
                            try
                            {
                                s.close();
                            }
                            catch (IOException e)
                            {
                                e.printStackTrace();
                            }
                        }
                    }
                });
                t2.start();
            }
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


    public static void main(String[] args) throws InterruptedException
    {
        Connection c = new Connection();
        Thread  t1 = new Thread(c);
        t1.setDaemon(true);
        t1.start();
        Runnable    r = new Runnable()
        {
            public void run()
            {
                try (Socket s = new Socket("localhost", 7000))
                {
                    DataOutputStream    dos = new DataOutputStream(s.getOutputStream());
                    DataInputStream dis = new DataInputStream(s.getInputStream());
                    for (int i = 0; i < 10; i++)
                    {
                        dos.writeUTF("Hello from "+Thread.currentThread().getName());
                        String  reply = dis.readUTF();
                        Thread.sleep(10*1000);
                    }
                }
                catch (IOException|InterruptedException exc)
                {
                    exc.printStackTrace();
                }
            }
        };
        Thread  t2 = new Thread(r);
        Thread  t3 = new Thread(r);
        t2.start();
        t3.start();
        t2.join();
        t3.join();
    }
}

Output:

Server is listening
Client Accepted
Server is listening
Client Accepted
Server is listening
Hello from Thread-1
Hello from Thread-2
Hello from Thread-2
Hello from Thread-1
Hello from Thread-2
Hello from Thread-1
Hello from Thread-2
Hello from Thread-1
Hello from Thread-1
Hello from Thread-2
Hello from Thread-1
Hello from Thread-2
Hello from Thread-2
Hello from Thread-1
Hello from Thread-1
Hello from Thread-2
Hello from Thread-2
Hello from Thread-1
Hello from Thread-2
Hello from Thread-1
user207421
  • 305,947
  • 44
  • 307
  • 483
  • My code is the same.. but it doesn't work.. Can it be a problem of java8? Or can it be something related to the difference btween my Clients ( one JavaApp and one Android)? – Alessio Trecani Feb 11 '16 at 23:09
  • 1
    Post your clients and I'll tell you. – user207421 Feb 11 '16 at 23:11
  • Ok I ve figured it out.. My serve now can listen from both Clients.. So the server displays all the messages.. but the Clients Don't receive the message sent by the other one. I m posting the clients code. – Alessio Trecani Feb 11 '16 at 23:18
  • 1
    I don't see any reason why those clients won't work. The clients aren't *supposed* to 'receive the messages sent by the other one'. Unclear what you're asking. – user207421 Feb 11 '16 at 23:27
  • Yes this is the point.. How can I set the client to be able to receive data also from other Client – Alessio Trecani Feb 11 '16 at 23:29
  • 1
    The server will have to *send* it to the other client. So it will need a list of client sockets and traverse them all when a message is received. – user207421 Feb 11 '16 at 23:31
  • Ok I though it would be this the solution.. I will try to create A Socket[] that storres all clients.. And Inside the loop I should create a for loop that write data(dos.wrtieUTF) to all the Clients inside Socket[].. I will post something when this is done Thanks so much for the help – Alessio Trecani Feb 11 '16 at 23:33
  • 1
    I strongly suggest a `List` instead of an array. Make sure you clean it up when the accepted socket gets closed. – user207421 Feb 11 '16 at 23:36
  • Really appreciated.. I will try it.. Thanks really much for your time – Alessio Trecani Feb 11 '16 at 23:37
  • I have updated the code and everything is solved.. But in this way when an exception is thrown My code close every time the first Socket in the list.. How can i understand which socket thrown the exception and close it? – Alessio Trecani Feb 12 '16 at 18:32