0

I have my server code below over here:

public void startServer() {
        ServerSocket listener = selectUnusedPortFromRange(1024, 65535);
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String command = null;
                    while (true) {
                        Socket socket = listener.accept();
                        System.out.println("Got a connection from: " + socket.getLocalPort());
                        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        command = in.readLine();
                        System.out.println("GOT HERE"); //Not being printed out
                        if (command != null && !"".equals(command)) {
                            if ("connection".equals(command)) {
                                Writer writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                                writer.write("success\n");
                                writer.flush();
                            }
                        }
                    }
                }
            }
        }
        t.start();
}

This is my client side:

public void makeConnection() {
    try {
        Socket socket = new Socket(IP, PORT);
        Writer writer = new PrintWriter(socket.getOutputStream(), true);
        writer.write("connection\n");
        BufferedReader socketRead = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String str;
        while ((str = socketRead.readLine()) != null) {
            if ("success".equals(str)) {
                System.out.println("Successfully saved all hosts to: " + listOfHosts.get(i));
                socketRead.close();
                socket.close();
                iStream.close();
                writer.close();
            }
        }
    }catch (Exception e) {
         System.out.println(e.getMessage());
    }
}

On the client side after I create my socket to the connect to the server I write "connection" into the outputStream of the socket and wait for an acknowledgement back from the server saying success. For some reason the connection is not being made to the server. In the server System.out.println("Got a connection from: " + socket.getLocalPort()); this line is not being printed out.

Is there something wrong that I am doing. I can't spot it. And I am not getting an exception thrown when I try to connect to my server.

  • Just a sanity check... is your client using the same port your server is binded to? I can't tell what `selectUnusedPortFromRange()` does, but my guess is it binds to a random unused port within your specified range? Make sure your client knows which port it bound to. – SnakeDoc Apr 14 '17 at 21:00
  • @cricket Yes I just noticed that and changed it. That was my typing mistake. I have changed it to the correct code in my post now. –  Apr 14 '17 at 21:00
  • 1
    Seen this? https://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html – OneCricketeer Apr 14 '17 at 21:01
  • @cricket_007 Yes I have followed that turoial. –  Apr 14 '17 at 21:05
  • @SnakeDoc Yes I am sure the client is not using the same port since I print out the ports and they are both different. –  Apr 14 '17 at 21:05
  • can you try entering "connection"+"\n" – opensam Apr 14 '17 at 21:06
  • @opensam That didn't seem to work either. But for some reason now on the server side I am getting the connection since this is being printing out `System.out.println("Got a connection from: " + socket.getLocalPort());` But now the print statement in the server: `System.out.println("GOT HERE");` is not being printed out. Can you take a look at that in my question. –  Apr 14 '17 at 21:11
  • 1
    @1290 They need to both use the same port. Your client is trying to talk to the server on a port it's not listening on. – SnakeDoc Apr 14 '17 at 21:17
  • It looks like you newer flushes your writer. You should flush it after writer.write. Otherwise the data might stay in the write buffer until you close the stream – MTilsted Apr 14 '17 at 21:18
  • @MTilsted Can you let me know after which `writer.write` I should flush it? The connection is being made but `command = in.readLine();` on the server is not getting anything. Is `command = in.readLine();` a blocking call? –  Apr 14 '17 at 21:39
  • Yes,after write.write("success"); add write.flush(); – MTilsted Apr 14 '17 at 21:40
  • @MTilsted The problem is though it is not getting past `command = in.readLine();` in the server code. I will try the `writer.flush()` still and see if it works. –  Apr 14 '17 at 21:42
  • have a look http://stackoverflow.com/questions/5987970/socket-bufferedreader-hangs-at-readline – opensam Apr 14 '17 at 21:42
  • @opensam That didn't seem to work as well. –  Apr 14 '17 at 21:45
  • @1290 The advice to add a `\n` to the end of your `writer.write()` calls is correct. So do something like: `writer.write("success\n");` and then `writer.flush();` just for good measure. – SnakeDoc Apr 14 '17 at 21:45

2 Answers2

0

1) Make sure you use the same port for both the Client and Server. They must communicate over the same port. It seems you may be using different ports currently.

2) Make sure you actually start your server thread. As-is in your code above, you make a new Thread, but never start it. t.start() must be called somewhere.

3) If this is on your local machine, you may be better off using localhost instead of the actual IP address. Firewalls might treat your external IP differently.

4) Terminate your messages with a newline character, such as \n, so that your BufferedReader can use it's readLine() method. For good measure, also follow-up by flushing the writer's buffer, just in case the newline character didn't trigger that. writer.flush();

And lastly, make sure you terminate the JVM before trying to run your code again. Your code has not shutdown mechanism to un-bind the server from the port... so you may get an exception thrown telling you the port and/or address are already in use. If that happens, either change ports, or kill the java process running in the background.

Here is your code, slightly modified to run on my system. It's working as you might expect it to. I tried to change as little as possible just to get it working on my system. One note is, I hard-coded the port number into the server and client - that's not required, it was just convenient for me to test with:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;

public class Test {
    public static void main(String[] args) throws IOException {
        Test test = new Test();
        test.startServer();
        test.makeConnection();
    }

    public void startServer() throws IOException {
        final ServerSocket listener = new ServerSocket(60001);
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String command = null;
                    while (true) {
                        Socket socket = listener.accept();
                        System.out.println("Got a connection from: " + socket.getLocalPort());
                        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        command = in.readLine();
                        System.out.println("GOT HERE");
                        if (command != null && !"".equals(command)) {
                            if ("connection".equals(command)) {
                                Writer writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                                writer.write("success\n");
                                writer.flush();
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
    }

    public void makeConnection() {
        System.out.println("Making Connection");;
        try {
            Socket socket = new Socket("localhost", 60001);
            Writer writer = new PrintWriter(socket.getOutputStream(), true);
            writer.write("connection\n");
            writer.flush();
            BufferedReader socketRead = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String str;
            while ((str = socketRead.readLine()) != null) {
                if ("success".equals(str)) {
                    System.out.println("Successfully saved all hosts to: "); //+ listOfHosts.get(i));
                    socketRead.close();
                    socket.close();
                    //iStream.close();
                    writer.close();
                }
            }
        }catch (Exception e) {
             System.out.println(e.getMessage());
        }
    }

}
SnakeDoc
  • 13,611
  • 17
  • 65
  • 97
  • OMG Thank you so much. Number 1 was ruled out, number 2 I forgot to add `t.start()` in my question (my typing error) sorry about that, number 3 (no firewalls), NUMBER 4 was the the main thing and your sample code helped a lot. Thank you!! –  Apr 14 '17 at 21:55
  • There is now one more issue.... In my server the `writer.write("success\n");` part is not being sent back to the client. It gets into the `if ("connection".equals(command)) { }` block but it is not sending back `writer.write("success\n");`. –  Apr 14 '17 at 21:58
  • @1290 Perhaps something else is different in your code vs. what I have above? When I run it on my system, I get the "`Successfully saved all hosts to: `" message displaying, which seems to be triggered in the client when it receives the `success` message from the server. – SnakeDoc Apr 14 '17 at 22:00
  • 1
    Are you sure you fixed your server to send `"success\n"`? The `readLine()` method used in your client is looking for a newline character... – SnakeDoc Apr 14 '17 at 22:02
  • Ok never mind it is working now. I accidently changed the string to "successadd" on the client so it wasn't catching the "success" from the server. Stupid mistake. Again thanks for the help! –  Apr 14 '17 at 22:03
  • 1
    @1290 No worries... we've all been there. :) – SnakeDoc Apr 14 '17 at 22:06
0

I was facing the exact same issue. I overcame it by using an ACK mechanism (Wasn't my idea, it was suggested to me). The idea is that client would make a request to server and keep the socket connection alive (and the ouput stream open) till server responds back an agreed ACK message over the same channel. Once the client receives the ACK message, only then it would close the connection.

Below is the code for Server :-

final ServerSocket listener = new ServerSocket(11111);
    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                String command = null;
                 while (true) {
                    System.out.println("About to accept");
                    Socket socket = listener.accept();
                    System.out.println("Got a connection from: " + socket.getLocalPort());
                    DataInputStream inputStream = new DataInputStream(socket.getInputStream());
                    StringBuilder str = new StringBuilder(inputStream.readUTF());
                    //command = in.readLine();
                    System.out.println("GOT HERE. Msg received : "+str); 
                    if (str != null && !"".equals(str.toString())) {
                        command = str.toString();
                        if ("connection".equals(command)) {
                            System.out.println("Got connection message");
                             DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
                            outputStream.writeUTF("connection");
                            outputStream.close();

                        }
                    }
                    inputStream.close();
                    System.out.println("Done");
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
            }
        }
});
    t.start();

}

Client :-

public void makeConnection() {
    try {
        System.out.println("In makeConnection");
        Socket socket = new Socket("127.0.0.1", 11111);
        DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
        outputStream.writeUTF("connection");
        InputStream inputStream = socket.getInputStream();
        DataInputStream dataInputStream = new DataInputStream(inputStream);
        StringBuilder str;
        do {
            str = new StringBuilder(dataInputStream.readUTF()); 
            } while (!str.toString().equals("connection"));
        System.out.println("Successfully saved all hosts to: ");
        outputStream.close();
        dataInputStream.close();
        socket.close();
        outputStream.close();
    }catch (Exception e) {
         System.out.println(e.getMessage());
    }
}

A call to start the proceedings :-

public void start() throws IOException, InterruptedException {
    System.out.println("Starting server");
    startServer();
    Thread.sleep(1000);
    System.out.println("Starting connection");
    makeConnection();
}
opensam
  • 368
  • 1
  • 4
  • 10