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);
}
