0

I just wanna make a Server application which gets Strings and put these into a JTextArea. There are two errors I get, even no errors are showed.

  1. the window can't be closed although I used this statement:

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

  2. If the client connects to the Server, the whole window turns black. What could be the error? Here the code:

Client:

public Main() {
    super("Main");
    setIconImage(Toolkit.getDefaultToolkit().getImage(Main.class.getResource("/images/ic.png")));

    panelFields = new JPanel();
    panelFields.setLayout(new BoxLayout(panelFields,BoxLayout.X_AXIS));
    panelFields2 = new JPanel();
    panelFields2.setLayout(new BoxLayout(panelFields2,BoxLayout.X_AXIS));

    scrollPane = new JScrollPane();
    panelFields.add(scrollPane);

    getContentPane().add(panelFields);
    getContentPane().add(panelFields2);
    getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.Y_AXIS));
    setSize(326, 264);
    setVisible(true);

    messagesArea = new JTextArea();
    scrollPane.setViewportView(messagesArea);
    messagesArea.setColumns(30);
    messagesArea.setRows(10);
    messagesArea.setEditable(false);

    startServer = new JButton("Start");
    startServer.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            socketConnection();
            startServer.setEnabled(false);
        }
    });

    panelFields.add(startServer);
}

And the Server connection:

private void socketConnection() {
    try {
        serverSocket = new ServerSocket(9090);
        System.out.println("Listening: " + serverSocket.getLocalPort());
    } catch (IOException e) {
        e.printStackTrace();
    }

    while (true) {
        try {
            socket = serverSocket.accept();
            dataInputStream = new DataInputStream(socket.getInputStream());
            System.out.println("ip: " + socket.getInetAddress());
            System.out.println("message: " + dataInputStream.readUTF());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (dataInputStream != null) {
                try {
                    dataInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Maybe you could tell me, how I can fix those problems and also, how I can make, that the server doesn't close the socket although the client disconnects. I wanna reconnect maybe later...

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
Simon Pio.
  • 115
  • 1
  • 14
  • [`WiindowEvent`](https://docs.oracle.com/javase/7/docs/api/java/awt/event/WindowEvent.html) – ruyili Jan 29 '16 at 21:49
  • Possible duplicate of https://stackoverflow.com/questions/182316/java-swing-libraries-thread-safety . Your socketConnection method never ends, which means your ActionListener never returns, which prevents Swing from processing any further events—including WindowEvents representing title bar close actions. Always perform lengthy operations in a thread other than the AWT Event Dispatch Thread. – VGR Jan 29 '16 at 21:51
  • Thanks, I got it. I just did it into a "new thread(){}" and it works perfectly! Could you maybe tell me, how I can run this thread the whole time in the background although the first connection crashed? – Simon Pio. Jan 29 '16 at 22:02

1 Answers1

1

You need to start your socket listener in its own thread, and you need to add a window close listener that shuts down that thread.

For example:

private ServerSocket serverSocket = null;
private boolean done = false;

private void startServer() {
    Thread t = new Thread(new Runnable() {
        public void Run() {
            socketConnection();
        });
    }
    t.start();
}

private void socketConnection() {
    try {
        serverSocket = new ServerSocket(9090);
        System.out.println("Listening: " + serverSocket.getLocalPort());

        while (!done) {
            try {
                final Socket socket = serverSocket.accept();
                Thread t = new Thread(new Runnable() {
                    public void Run() {
                        handle(socket);
                    }
                });
                t.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void handle(Socket socket) {
    if (socket == null) return;
    try {
        dataInputStream = new DataInputStream(socket.getInputStream());
        System.out.println("ip: " + socket.getInetAddress());
        System.out.println("message: " + dataInputStream.readUTF());
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (dataInputStream != null) {
            try {
                dataInputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        try {
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


public void windowClosing(WindowEvent e) { 
    done = true; 
    socketServer.close(); 
} 

Your button click listener should call startServer(), then your window close function would set done = true and call socketServer.close().

Now you have one thread for the UI, one thread for the socket server, and one thread for each connection to the server.

Andrew Young
  • 311
  • 2
  • 5
  • Thank you very much for your fast answer! It helped me! I just got another question... I can't set "done" true before the connection has occured. So first, I set "done" false and ... when do I set "done" true? I wanna keep this server alive, so that I can reconnect anytime? – Simon Pio. Jan 29 '16 at 22:26
  • You only set done=true when you're ready for the program to close, so inside a window close listener. – Andrew Young Jan 29 '16 at 22:27
  • public void windowClosing(WindowEvent e) { done = true; socketServer.close(); } – Andrew Young Jan 29 '16 at 22:28
  • Thank you very much! Since I can just close the window and the whole applications stops working, it seems that I don't need a window close listener. I am new to java, so maybe I am wrong. Anyway, thank you very much for your help! – Simon Pio. Jan 29 '16 at 22:33
  • Because you set "close on exit" it forces the threads to end when you close the window, so you get your desired effect. :) – Andrew Young Jan 29 '16 at 22:36
  • A Last question. I just got the first message sent by the client (Android) but I don't get another message. Do I have to do this with an interface (Callback method) or is there an easier way? – Simon Pio. Jan 29 '16 at 23:13
  • It should work ok the way it is. As long as done != true and no exceptions have been thrown by the serverSocket object, then the server socket should continue to accept connections and your code will start worker threads to handle those connections. – Andrew Young Jan 30 '16 at 10:30