JavaFX and network
I am a novice in socket and network programming. This is my attempt to create a simple chat server. My code seems to have no errors (as far as I know). It compiles well, but when I try to run it, I seem to be in trouble and do nothing
Sorry, if such a thing has been asked, I can't find anything, but I'm not sure what the problem is, so I really don't know what to look for
The server:
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.socket; import java.util.Date; import javafx.scene.Scene; import javafx.scene.control.TextArea; import javafx.stage.Stage; public class ChatServer extends Stage { TextArea informationArea = new TextArea(); String message = null; public ChatServer() { informationArea.setEditable(false); setTitle("Chat Server"); setScene(new Scene(informationArea,500,300)); show(); try { ServerSocket serverSocket = new ServerSocket(8000); informationArea.appendText("Server started at " + new Date() + '\n'); int clientNumber = 1; while(true) { Socket socket = serverSocket.accept(); InetAddress inetAddress = socket.getInetAddress(); informationArea.appendText( "Client: " + clientNumber++ + "\n\thost name: " + inetAddress.getHostName() + "\n\tIP address " + inetAddress.getHostAddress() + "\n\n" ); ClientHandler task = new ClientHandler(socket); new Thread(task).start(); } } catch(IOException ex) { System.err.println(ex); } } class ClientHandler implements Runnable { private Socket socket; ClientHandler(Socket socket) { this.socket = socket; } @Override public void run() { try { DataInputStream inputFromClient = new DataInputStream(socket.getInputStream()); DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream()); while (true) { if (message != null) { outputToClient.writeUTF(message); } message = inputFromClient.readUTF(); } } catch(IOException e) { System.err.println(e); } } } }
The class that runs it:
import javafx.application.Application; import javafx.stage.Stage; public class RunChatServer extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { stage = new ChatServer(); } }
I appreciate the reasons for input errors, why, the correct way to achieve this goal, and suggestions of any style, because this is my first attempt, and I don't know the traditional way to achieve this goal
Update: I think maybe it's related to blocking UI threads. I added import JavaFX concurrent. Task and refactor my clienthandler class, as follows:
class ClientHandler extends Task { private Socket socket; ClientHandler(Socket socket) { this.socket = socket; } @Override public Void call() { try { DataInputStream inputFromClient = new DataInputStream(socket.getInputStream()); DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream()); while (true) { if (message != null) { outputToClient.writeUTF(message); outputToClient.flush(); } message = inputFromClient.readUTF(); } } catch(IOException e) { System.err.println(e); } return null; } }
But it doesn't solve any problems
Solution
Instead of blocking the constructor, put the server's loop that accepts sockets in its own thread
try { ServerSocket serverSocket = new ServerSocket(8000); informationArea.appendText("Server started at " + new Date() + '\n'); new Thread(() -> { int clientNumber = 1; while (true) { try { Socket socket = serverSocket.accept(); InetAddress inetAddress = socket.getInetAddress(); Platform.runLater(() -> informationArea.appendText( "Client: " + clientNumber++ + "\n\thost name: " + inetAddress.getHostName() + "\n\tIP address " + inetAddress.getHostAddress() + "\n\n" ) ); ClientHandler task = new ClientHandler(socket); new Thread(task).start(); } catch (IOException ex) { Logger.getLogger(ChatServer.class.getName()).log(Level.SEVERE,null,ex); } } }).start(); } catch (IOException ex) { System.err.println(ex); }