0

I am new to sockets in JAVA. Recently, I am trying to build a server-client program that clients can search a word from the dictionary in server side and the server will return the defintion of the word to the clients. The code in server side is as the following:

public class DictionaryServer {

private static int port;
private static String dicFile;
static Map<String, String> dictionary = new HashMap<String, String>();
int userCounter = 0;

public static void main(String[] args) {

    //check if starting the server in valid format
    if (args.length != 2) {
        System.err.println("Invalid format to start DictionaryServer"); 
        System.err.println("Usage: java DictionaryServer <port number> <the name of dictionary>");
        System.exit(1);
    }


    port = Integer.parseInt(args[0]);
    dicFile = args[1];


    try{
        System.out.println("IP: " + InetAddress.getLocalHost());
        System.out.println("port: " + port);
    }
    catch(UnknownHostException e){
        e.printStackTrace();
    }
    DictionaryServer s = new DictionaryServer();
    s.server(port, dicFile);

}


public void server(int port, String dicFile) {
    ServerSocketFactory serverSocket = ServerSocketFactory.getDefault();

    try(ServerSocket server = serverSocket.createServerSocket(port)){

        System.out.println("Server IP: " + server.getInetAddress());
        System.out.println("Listening for client connections...");

        while(true){
            Socket client = server.accept();
            System.out.println("Client \"" + client.getRemoteSocketAddress().toString()
                    + "\""+ " is connecting.");


            Thread t = new Thread(() -> service(client, dicFile));
            t.start();

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

}

public void service(Socket client, String dicFile){
    try(Socket clientSocket = client){
        // Input and Output stream of the client
        DataInputStream input = new DataInputStream(
                clientSocket.getInputStream());
        DataOutputStream output = new DataOutputStream(
                clientSocket.getOutputStream());

        //check request
        int action = input.readInt();   //1:add, 2:remove, 3:query
        String word = input.readUTF();

        //choose action
        Dic d = new Dic(dicFile);
        switch(action){
            case 1: //add
                String definition = input.readUTF();
                output.writeUTF(d.add(word, definition, dicFile));
                break;

            case 2: //remove
                output.writeUTF(d.remove(word, dicFile));
                break;

            case 3: //query
                output.writeUTF(d.query(word, dicFile));
                break;
        }
    }
    catch(IOException e){
        String message=e.getMessage();
        System.out.println(message);
        System.out.println();
    }   
}   

I am got stucked in an error when I try to restart the serverprogram: java.net.BindException: Address already in use (Bind failed)

For example, last time I execute the server program with the port 4000 and it worked, but if I want to execute the server program with the same port again, the exception will show up. I checked what the port 4000 is doing by "lsof -i:4000" in terminal which told me:

COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    19683 Andy    7u  IPv6 0x43e8f876eb74b731      0t0  TCP *:terabase (LISTEN)

Does anyone know how I can fix this problem? Thank you!

Andy Lu
  • 29
  • 1
  • 7
  • 1
    Once the application terminates, the port is eventually released by the OS. It just takes some time. – DYZ Aug 26 '17 at 06:18
  • You must kill the previous running servers or make your port be configurable at runtime to be different – OneCricketeer Aug 26 '17 at 06:20
  • Thanks for reply. But I have waited for a long while but they are still in LISTEN. Is it possible that I can terminate them when I exit the server program by add some codes? For no the only way works is to close my Eclipse. – Andy Lu Aug 26 '17 at 06:25
  • Killing the main thread does not kill the whole JVM when other non daemon threads are still running. Try `Thread.setDaemon(true)`. For more info see https://stackoverflow.com/a/2213348/2920861 – Crigges Aug 26 '17 at 07:28

1 Answers1

1

You need make sure your program has really exited, and you also need to set reuseAddress. To do that you have to create the server socket without binding, set the option, and then bind it, in three different steps:

ServerSocket server = serverSocketFactory.createServerSocket();
server.setReuseAddress(true);
server.bind(new InetSocketAddress(port));
user207421
  • 305,947
  • 44
  • 307
  • 483