I am making a program, and I don't know why my program becomes unresponsive, when I click the button ):
I have a feeling its because of this:
"connection = server.accept();"
I don't know how to fix it.

I am trying to recreate this:
https://stackoverflow.com/questions/18505123/how-to-use-client-chat-on-different-pc

but in javafx.

package yeetYeet;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Server extends Application{

       private ObjectOutputStream output;
       private ObjectInputStream input;
       private ServerSocket server;
       private Socket connection;

    //set up and run the server
    private void startRunning() {
        try{
             server = new ServerSocket(6789, 100);

             new AnimationTimer() {

                @Override
                public void handle(long arg0) {
                    try{
                       waitForConnection();
                       setupStreams();
                       whileChatting();
                    }catch(EOFException eofException){
                       showMessage("\n Server ended the connection! ");
                    }catch (IOException IOException){
                        IOException.printStackTrace();
                    }finally{
                       closeCrap();
                    }
                }
             }.start();
          }catch(IOException ioException){
             ioException.printStackTrace();
          }
    }

    //wait for connection, then display connection information
    private void waitForConnection() throws IOException {
        showMessage(" Waiting for someone to connect... \n");
        connection = server.accept();
        showMessage(" Now connected to " + connection.getInetAddress().getHostName());
    }

    //get stream to send and receive data
    private void setupStreams() throws IOException {
        output = new ObjectOutputStream(connection.getOutputStream());
        output.flush();
        input = new ObjectInputStream(connection.getInputStream());
        showMessage("\n Streams are now setup! \n");
    }

    //during the chat conversation
    private void whileChatting() throws IOException {
        String message = " You are now connected! ";
        sendMessage(message);
        ableToType(true);
        do {
            try {
                message = (String) input.readObject();
                showMessage("\n" + message);
            }catch(ClassNotFoundException classNotFoundException) {
                showMessage("\n idk wtf that user sent!");
            }
        }while(!message.equals("CLIENT - END"));
    }

    //close streams and sockets after you are done chatting
    private void closeCrap() {
        showMessage("\n Closing connections... \n");
        ableToType(false);
        try {
            output.close();
            input.close();
            connection.close();
        }catch(IOException ioException) {
            ioException.printStackTrace();
        }
    }

    //send a message to client
    private void sendMessage(String message) {
        try {
            output.writeObject("SERVER - " + message);
            output.flush();
            showMessage("\nSERVER - " + message);
        }catch(IOException ioException) {
            ta.appendText("\n ERROR: DUDE I CANT SEND THAT MESSAGE");
        }
    }

    //updates chatWindow
    private void showMessage(final String text) {
        new AnimationTimer() {

            @Override
            public void handle(long arg0) {
                ta.appendText(text);
            }
        }.start();
    }

    //let the user type stuff into their box
    private void ableToType(final boolean tof) {
        new AnimationTimer() {

            @Override
            public void handle(long arg0) {
                tf.setEditable(tof);
            }
        }.start();
    }

    private Group serverGR;
    private Scene serverSC;
    private Stage window;
    private TextField tf;
    private TextArea ta;
    private Button connectingStart;

    @Override
    public void start(Stage primaryStage) throws Exception {
        serverGR = new Group();
        serverSC = new Scene(serverGR, 1280, 720, Color.PALEGREEN);

        window = primaryStage;
        window.setScene(serverSC);
        window.setTitle("Bleidorb -\\\\\"Server\"\\\\- ChatProgram");
        window.show();

        tf = new TextField();
        tf.setTranslateX(10);
        tf.setTranslateY(10);
        tf.setPrefWidth(500);
        tf.setPrefHeight(20);
        tf.appendText("type your message here");
        serverGR.getChildren().add(tf);

        ta = new TextArea();
        ta.setTranslateX(10);
        ta.setTranslateY(40);
        ta.setPrefWidth(500);
        ta.setPrefHeight(500);
        serverGR.getChildren().add(ta);

        connectingStart = new Button("Connection Start");
        connectingStart.setTranslateX(600);
        connectingStart.setTranslateY(300);
        connectingStart.setPrefWidth(150);
        connectingStart.setPrefHeight(30);
        connectingStart.setOnAction(e -> {
            startRunning();
        });
        serverGR.getChildren().add(connectingStart);
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Recommended Answers

All 16 Replies

To me it should appear to hang on line 57. Why? "The accept method waits until a client starts up and requests a connection on the host" is right out of the documentation. This app will sit there, waiting.

^ like he said.

Waiting for a connection has to be done in its own thread if you want the app to respond to anything else while waiting.
Same goes for the whileChatting loop

I put "connection = server.accept();" in a loop and the freeze stopped, but I get errors from "output.close();"

private void waitForConnection() throws IOException {
    new AnimationTimer() {
        @Override
        public void handle(long now) {
            showMessage(" Waiting for someone to connect... \n");
            try {
                connection = server.accept();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            showMessage(" Now connected to " + connection.getInetAddress().getHostName());
        }
    }.start();
}

I don't know what you mean with thread

OK, that's going to be a problem with an app like this. Threads and Threading are a fundamental topic in computing, and relate to how a program can do multiple things at the same time (eg respond to user input while waiting for a network connectin). To do two things like that at the same time required two threads. You are converting a Swing application, but Swing and JavaFX use threads in slightly different ways (see techy note below), so the code cannot always be simply tramslated.
All I can suggest is that you find a tutorial about threads on the web that matches your current level of expetise, then check out some of the web sites that explain how JavaFX uses threads.

ps: I have no idea why you are using those AnimationTimers - you do know that their handle methods will be called 60 times per second?

Techy note: A Swing app starts in the main program thread and Swing has its own thread for any UI stuff. That means you can exter a wait-for-connection in your startup code (main app thread) while UI events continue to be handled. JavaFX calls your start method on the same thread that it uses to handle UI events,so it you wait in the start method all UI events are blocked. (AnimationTimer handle methods are also queued/called on the same thread.)

So basicly I have to find a way to unblock ui events in my program

Yes, or, more accurately, avoid blocking them in the first place. The most obvious way is start a new thread and call your waitForConnection() in that thread. Like that it can sit waiting for connections without blocking any other activity. You may need to read up on threads in general to get the concepts, but having done that it's like 1 line of code to do it in Java.

This is a part of an example from a JavaFX (Server/Client) program
this is from Almas Baimagambetov
https://www.youtube.com/watch?v=VVUuo9VO2II

I have the code, but is there something I can get from there?

btw, I am new on this forum, it says "Curly braces { } may only be used when posting code.".

is there a way to share the example?

If you want to post code do it as part of a code block or inline ciode (icons 3 and 4 above the text input box). But if it's someone else's example code then no, you cannot post it here or anywhere else without the copyright owner's permission.
I watched about 15 secs from near the beginning and the first thing I saw was a Thread for the connect, so that's a good start. Unfortunately the way he did it is not recommended best practice.

What part of " if it's someone else's example code then no, you cannot post it here or anywhere else without the copyright owner's permission." didn't you understand?

Research the concepts and write your own code. It's the only way to learn.

//I don't know what I have done, but I did this.
//The freezing thing is not here anymore, because of the "new Runnable{ run method}" thing.

package com.VINSTORM.VinvinBleidorb_aka_BleidorbPerfect.chatprogramTest;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class ServerChatProgram extends Application{

    private ObjectOutputStream output;
    private ObjectInputStream input;
    private ServerSocket server;
    private static Socket connection;

    private Stage window;
    private Scene scene;
    private Group root;
    private TextField inputMessages;
    private TextArea viewsMessages;

    private void startRunning() {
        try{
            waitForConnection();
            setupStreams();
            whileChatting();
         }catch(EOFException eofException){
            showMessage("\n Server ended the connection! ");
         }catch (IOException IOException){
            IOException.printStackTrace();
         }finally{
            closeCrap();
         }
    }
    private void waitForConnection() throws IOException{
        new Runnable(){
            @Override
            public void run() {
                showMessage(" Waiting for someone to connect... \n");
                try {
                    connection = server.accept();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                showMessage(" Now connected to " + connection.getInetAddress().getHostName());
        }};
    }

    private void setupStreams() throws IOException{}
    private void whileChatting() throws IOException{}
    private void closeCrap(){}
    private void sendMessage(String message){}
    private void showMessage(final String text){}
    private void ableToType(final boolean tof){}

    private void createContent() {

        inputMessages = new TextField();
        inputMessages.setTranslateX(10);
        inputMessages.setTranslateY(10);
        inputMessages.setPrefWidth(340);
        inputMessages.setPrefHeight(20);

        viewsMessages = new TextArea();
        viewsMessages.setTranslateX(10);
        viewsMessages.setTranslateY(50);
        viewsMessages.setPrefWidth(340);
        viewsMessages.setPrefHeight(300);

        inputMessages.setOnAction(event -> {
            String Message = "Server: ";
            Message += inputMessages.getText();
            inputMessages.clear();
            viewsMessages.appendText(Message + "\n");
        });

        root = new Group(inputMessages, viewsMessages);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        createContent();
        scene = new Scene(root, 640, 360, Color.LIGHTCYAN);
        window = primaryStage;
        window.setScene(scene);
        window.setTitle("Server \\\\ ChatProgram \\\\ Test");
        window.show();

        startRunning();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

//I did this, but I saw nothing in the console, the waitForConnection() method does nothing ):

private void startRunning() {
        try{
            waitForConnection();
            setupStreams();
            whileChatting();
         }catch(EOFException eofException){
            showMessage("\n Server ended the connection! ");
         }catch (IOException IOException){
            IOException.printStackTrace();
         }finally{
            closeCrap();
         }
    }
    private void waitForConnection() throws IOException{
        new Runnable(){
            @Override
            public void run() {
                showMessage(" Waiting for someone to connect... \n");
                System.out.println("hello");
                try {
                    connection = server.accept();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                showMessage(" Now connected to " + connection.getInetAddress().getHostName());
                System.out.println(connection.getInetAddress().getHostName().toString());
        }};
    }
//I forgot to put this in my code:
//"server = new ServerSocket(6789, 100);"

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class ServerChatProgram extends Application{

    private ObjectOutputStream output;
    private ObjectInputStream input;
    private ServerSocket server;
    private static Socket connection;

    private Stage window;
    private Scene scene;
    private Group root;
    private TextField inputMessages;
    private TextArea viewsMessages;

    private void startRunning() {
        try {
            server = new ServerSocket(6789, 100);
            new AnimationTimer() {

                @Override
                public void handle(long now) {
                    try{
                        waitForConnection();
                        setupStreams();
                        whileChatting();
                     }catch(EOFException eofException){
                        showMessage("\n Server ended the connection! ");
                     }catch (IOException IOException){
                        IOException.printStackTrace();
                     }finally{
                        closeCrap();
                     }
                }
             }.start();
        }catch(IOException ioException) {
            ioException.printStackTrace();
        }
    }
    private void waitForConnection() throws IOException{

            showMessage(" Waiting for someone to connect... \n");
            System.out.println("hello");
        try {
            connection = server.accept();
        }catch (IOException e) {
            e.printStackTrace();
        }
            showMessage(" Now connected to " + connection.getInetAddress().getHostName());
            System.out.println(connection.getInetAddress().getHostName().toString());
    }

    private void setupStreams() throws IOException{}
    private void whileChatting() throws IOException{}
    private void closeCrap(){}
    private void sendMessage(String message){}
    private void showMessage(final String text){
        Platform.runLater(() -> {
            viewsMessages.appendText(text);
        });
    }
    private void ableToType(final boolean tof){}

    private void createContent() {

        inputMessages = new TextField();
        inputMessages.setTranslateX(10);
        inputMessages.setTranslateY(10);
        inputMessages.setPrefWidth(340);
        inputMessages.setPrefHeight(20);

        viewsMessages = new TextArea();
        viewsMessages.setTranslateX(10);
        viewsMessages.setTranslateY(50);
        viewsMessages.setPrefWidth(340);
        viewsMessages.setPrefHeight(300);

        inputMessages.setOnAction(event -> {
            String Message = "Server: ";
            Message += inputMessages.getText();
            inputMessages.clear();
            viewsMessages.appendText(Message + "\n");
        });

        root = new Group(inputMessages, viewsMessages);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        createContent();
        scene = new Scene(root, 640, 360, Color.LIGHTCYAN);
        window = primaryStage;
        window.setScene(scene);
        window.setTitle("Server \\\\ ChatProgram \\\\ Test");
        window.show();

        startRunning();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

new Runnable(){@Override public void run() {}};

Thats one part of one way to start a new thread. Without the other part it does nothing.
You still have AnimationTimers that make no sense at all.

You are now wasting your time (and mine) by cutting and pasting code you don't understand.

Read about threads in computing.
Then read about threads in Java (see the Oracle tutorials)
Then read about threads in JavaJX
Then you will know what you need to do, and why.

There is no short cut to this. Do it properly or don't do it.

commented: I am going to do that, sorry for wasting your time, I am going to do my very best to understand this topic. +0
commented: Here's hoping Vin Vin will wake up soon. Elsewhere this would result in much worse. +15

I somehow got this, I made a new class and I extended to Thread,
I did then this, I don't know what this is called:
but like so, "ServerInnerClass sic = new ServerInnerClass();"
then I started the thread, by doing this. sic.start();
in the ServerInnerClass, I made the run method.
And I placed the socket.accept in there.
Does this stop from lagging? freezing? IDK what it is called, but this fixed it.
of course, I know a little bit of threading (:
and I need to learn more about it.

I will finish my server-client program thing. And I might post a minimalistic example
of this answer.

source link that helped me: http://tutorials.jenkov.com/java-concurrency/creating-and-starting-threads.html

OK, yes. You have created a new thread for the server accept, so it no longer blocks anything else. That's good.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.