在 JavaFX 的客户端服务器聊天应用程序中向所有人发送消息
Send Message to All in Client Server Chat Application in JavaFX
我能够向连接到服务器的客户端发送消息,但是当
- 当 Client Bunny 向 Joel 发送消息(接收消息)时,反之亦然。
- 当Bunny第二次给Joel发消息时(没有收到消息)。
如何再次迭代哈希表循环以发送和接收消息。
服务器Class
import java.io.*; //Input and output to read and write data.
import java.net.*; //serversocket and initaddress
import java.util.Date; //to get date
import java.util.Enumeration; //enumeration
import java.util.Hashtable; // hashtable
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javafx.application.Application; //
import javafx.application.Platform; //platformrun later to append text
import javafx.event.EventHandler; // on click actions
import javafx.geometry.Insets; //insets
import javafx.geometry.Pos; //position
import javafx.scene.Scene; //scene
import javafx.scene.control.TextArea; //textarea
import javafx.scene.layout.StackPane; //stackpane
import javafx.stage.Stage; //stage
import javafx.stage.WindowEvent; //event close
public class Server extends Application { //class server
static InetAddress inetAddress; //inetaddress
private final Hashtable<Object, Object> outputStreams = new Hashtable(); //hashtable
TextArea textarea = new TextArea(); //textarea
static DataInputStream inputFromClient = null; //datainputstream
static DataOutputStream outputToClient = null; //dataoutputstream
static int clientNo = 0; //client connected
static ServerSocket serverSocket; //server socket
Hashtable<Object, Object> hmap = new Hashtable<>();
@Override // Override the start method in the Application class
public void start(Stage primaryStage) { //Stage to show everything
StackPane root = new StackPane(); //root add all the elements
root.setPadding(new Insets(10, 10, 10, 10)); //padding
root.setAlignment(textarea, Pos.CENTER); //positioning textarea to center
textarea.setMaxSize(400, 400); //maxsize of textarea
textarea.setWrapText(true); //wraptext for the textarea
new Thread(() -> { //thread to hold the server for the connections
try {
// Create a server socket
ServerSocket serverSocket = new ServerSocket(8001); //The server creates a server socket and, once a connection to a client is established, connects to the client with a client socket.
textarea.appendText("MultiThreadServer started at " + new Date() + '\n'); //server started with date.
while (true) { //accept multiple connections
// Listen for a new connection request
Socket socket = serverSocket.accept(); //listening for new connection from server port.
// inputFromClient = new DataInputStream(socket.getInputStream());
outputToClient = new DataOutputStream(socket.getOutputStream()); //outputstream to output to client
// Increment clientNo
clientNo++;
Platform.runLater(() -> {
// Display the client number
textarea.appendText("Starting thread for client " + clientNo + " at " + new Date() + '\n');
// Find the client's host name, and IP address
InetAddress inetAddress = socket.getInetAddress();
textarea.appendText("Client " + clientNo + "'s host name is " + inetAddress.getHostName() + "\n");
textarea.appendText("Client " + clientNo + "'s IP Address is " + inetAddress.getHostAddress() + "\n");
});
HandleAClient hd = new HandleAClient(socket);
hmap.put(socket, outputToClient);
hd.start();
// outputStreams.put(socket, outputToClient); //using hashtable to store client socket and outputstream
// Create and start a new thread for the connection
// new HandleAClient(this, socket);
}
} catch (IOException ex) {
textarea.appendText(ex + " \n");
}
}).start();
root.getChildren().addAll(textarea); // add UI elements to the root
Scene scene = new Scene(root, 450, 400); // creating scene of size 450 width and height 500
primaryStage.setTitle("Server"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() { //close scene
@Override
public void handle(WindowEvent t) {
primaryStage.close();
Platform.exit();
System.exit(0);
}
});
}
// Used to get the output streams
Enumeration getOutputStreams() {
return outputStreams.elements();
}
// Used to send message to all clients
void sendToAll(String message) {
// Go through hashtable and send message to each output stream
for (Enumeration e = getOutputStreams(); e.hasMoreElements();) {
DataOutputStream dout = (DataOutputStream) e.nextElement();
try {
// Write message
dout.writeUTF(message);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
class HandleAClient extends Thread {
private Socket socket; // A connected socket
private String text = "";
/**
* Construct a thread
*/
public HandleAClient(Socket socket) throws IOException {
this.socket = socket;
}
/**
* Run a thread
*/
public void run() {
try {
// Create data input stream
inputFromClient = new DataInputStream(socket.getInputStream()); //receive input from client
textarea.appendText(new Date() + " Connection from " + socket + "\n");//showing connection from client
text = inputFromClient.readUTF(); // read string or message from client
// serversocket.sendToAll(text);
Set set = hmap.entrySet();
Iterator it = set.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
System.out.println("key " + entry.getKey() + " : " + entry.getValue());
DataOutputStream dout = (DataOutputStream) entry.getValue();
dout.writeUTF(text);
dout.flush();
}
Platform.runLater(() -> {
textarea.appendText(new Date() + " " + text + "\n");//append text
});
} catch (IOException e) {
textarea.appendText("Error " + e + " \n");
try {
this.socket.close(); //socket close
} catch (IOException ex) {
textarea.appendText("Error " + e + " \n");
}
e.printStackTrace();
}
}
}
public static void main(String[] args) { //The keyword void simply tells the compiler that main( ) does not return a value.
launch(args);
}
}
Client Class
import java.io.*; //Input and output to read and write data.
import java.net.*; //serversocket and initaddress
import javafx.application.Application; //
import javafx.application.Platform; //platformrun later to append text
import javafx.event.EventHandler; // on click actions
import javafx.geometry.Insets; //insets
import javafx.geometry.Pos; //position
import javafx.scene.Scene; //scene
import javafx.scene.control.TextArea; //textarea
import javafx.scene.layout.StackPane; //stackpane
import javafx.stage.Stage; //stage
import javafx.stage.WindowEvent; //event close
import javafx.scene.control.Button; // button
import javafx.scene.control.Label; //label
import javafx.scene.control.TextField; //textfield
public class Client extends Application {
// IO streams
static DataOutputStream toServer = null; //datainputstream
static DataInputStream fromServer = null; //dataoutputstream
Label usernamelabel = new Label("Set your name :"); //set name label
Label textarealabel = new Label("Type your message in the textarea"); //text label
Label textlabel = new Label("Enter Text :"); //enter text
TextField textfield = new TextField(); //textfield
TextField namefield = new TextField(); //name field
Button send = new Button("Send"); //sendbutton
TextArea messagefield = new TextArea(); //textarea
static ServerSocket serverSocket; //serversocket
// Override the start method in the Application class
public void start(Stage primaryStage) throws IOException {
StackPane root = new StackPane(); //stacpane
root.setPadding(new Insets(10, 10, 10, 10));
StackPane.setAlignment(usernamelabel, Pos.TOP_LEFT);
namefield.setMaxWidth(200);
StackPane.setAlignment(namefield, Pos.TOP_CENTER);
StackPane.setMargin(textlabel, new Insets(30, 0, 0, 0));
StackPane.setMargin(textfield, new Insets(30, 0, 0, 0));
StackPane.setAlignment(textlabel, Pos.TOP_LEFT);
textfield.setMaxWidth(200);
StackPane.setAlignment(textfield, Pos.TOP_CENTER);
StackPane.setAlignment(send, Pos.BOTTOM_CENTER);
messagefield.setMaxSize(450, 250);
StackPane.setAlignment(textarealabel, Pos.BOTTOM_CENTER);
StackPane.setMargin(textarealabel, new Insets(0, 0, 35, 0));
StackPane.setAlignment(messagefield, Pos.CENTER);
root.getChildren().addAll(usernamelabel, namefield, send, messagefield, textarealabel, textlabel, textfield); //adding all the UI elements
// Create a scene and place it in the stage
Scene scene = new Scene(root, 500, 400);
primaryStage.setTitle("Client"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
send.setOnAction(e -> { //send button action
try {
if (namefield.getText().trim().length() == 0) { //name field is empty
messagefield.appendText("Name field is empty. Please enter your name\n");
} else if (textfield.getText().trim().length() == 0) { //message field is empty
messagefield.appendText("Message field is empty. Please enter your message to send\n");
}
// Send the radius to the server
if (namefield.getText().trim().length() > 0 && textfield.getText().trim().length() > 0) {
toServer.writeUTF(namefield.getText().trim() + " : " + textfield.getText().trim());
toServer.flush();
}
} catch (IOException ex) {
messagefield.appendText(ex+" \n");
}
});
try {
// Create a socket to connect to the server
Socket socket = new Socket("localhost", 8001); //socket with port number to connect server
// Create an output stream to send data to the server
toServer = new DataOutputStream(socket.getOutputStream());
new ReceiveMessage(socket); // send socket receieve class
// }
} catch (Exception ex) {
messagefield.setText(ex.toString() + '\n');
}
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() { //scene close
@Override
public void handle(WindowEvent t) {
Platform.exit();
System.exit(0);
}
});
}
class ReceiveMessage implements Runnable { //class receive message
private final Socket socket;//socket
public ReceiveMessage(Socket socket) { // constructor
this.socket = socket; //socket intializes
Thread thread = new Thread(this);
thread.setDaemon(true);
thread.start();
}
public void run() {
try {
fromServer = new DataInputStream(socket.getInputStream()); //to read from server
while (true) { // to continously receieve messages
// Get area from the server
String textmessage = fromServer.readUTF(); //read message from server
toServer.flush(); // flush
Platform.runLater(() -> {
messagefield.appendText(textmessage + " \n"); //append to textarea
});
}
} catch (IOException e) {
messagefield.appendText("Error " + e);
}
}
}
public static void main(String[] args) { //The keyword void simply tells the compiler that main( ) does not return a value.
launch(args);
}
}
服务器 class 已执行并占用客户端
客户端一已连接
客户端二连
谢谢。
我在代码中犯的错误是在客户端向服务器发送消息并在服务器连接暂停或停止后向所有连接到服务器的客户端发送消息我不知道为什么。我使用枚举方法向连接到服务器的所有客户端发送消息。这就是我解决问题的方法。希望我的回答对尝试使用线程实现客户端-服务器(多客户端)聊天应用程序的人有所帮助。
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class Server extends Application {
static InetAddress inetAddress;
private final Hashtable<Object, Object> outputStreams = new Hashtable();
TextArea textarea = new TextArea();
static int clientNo = 0;
static ServerSocket serverSocket;
Hashtable<Object, Object> hmap = new Hashtable<>();
ArrayList<Object> clients = new ArrayList<Object>();
public void start(Stage primaryStage) {
StackPane root = new StackPane();
root.setPadding(new Insets(10, 10, 10, 10));
root.setAlignment(textarea, Pos.CENTER);
textarea.setMaxSize(400, 400);
textarea.setWrapText(true);
root.getChildren().addAll(textarea);
Scene scene = new Scene(root, 450, 400);
primaryStage.setTitle("Server");
primaryStage.setScene(scene);
primaryStage.show(); // Display the stage
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent t) {
primaryStage.close();
Platform.exit();
System.exit(0);
}
});
new Thread(() -> {
listen();
}).start();
}
private void listen() {
try {
// Create a server socket
serverSocket = new ServerSocket(8001);
textarea.appendText("MultiThreadServer started at " + new Date() + '\n');
while (true) {
Socket socket = serverSocket.accept();
inputFromClient = new DataInputStream(socket.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
clientNo++;
Platform.runLater(() -> {
textarea.appendText("Starting thread for client " + clientNo + " at " + new Date() + '\n');
InetAddress inetAddress = socket.getInetAddress();
textarea.appendText("Client " + clientNo + "'s host name is " + inetAddress.getHostName() + "\n");
textarea.appendText("Client " + clientNo + "'s IP Address is " + inetAddress.getHostAddress() + "\n");
});
hmap.put(socket, outputToClient);
new HandleAClient(socket);
}
} catch (IOException ex) {
textarea.appendText(ex + " \n");
}
}
Enumeration getOutputStreams() {
return hmap.elements();
}
void sendToAll(String message) {
for (Enumeration e = getOutputStreams(); e.hasMoreElements();) {
DataOutputStream dout = (DataOutputStream) e.nextElement();
try {
dout.writeUTF(message);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
void All(String text) throws IOException {
Set set = hmap.entrySet();
Iterator it = set.iterator();
System.out.println("Text " + text);
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
System.out.println("key " + entry.getKey() + " : " + entry.getValue());
DataOutputStream dout = (DataOutputStream) entry.getValue();
dout.writeUTF(text);
dout.flush();
}
}
class HandleAClient extends Thread {
private final Socket socket; // A connected socket
private String text = "";
/**
* Construct a thread
*/
public HandleAClient(Socket socket) throws IOException {
this.socket = socket;
start();
}
/**
* Run a thread
*/
public void run() {
try {
DataInputStream inputFromClient = new DataInputStream(socket.getInputStream()); //receive input from client
while (true) {
textarea.appendText(new Date() + " Connection from " + socket + "\n");
text = inputFromClient.readUTF();
serversocket.sendToAll(text);
All(text);
Platform.runLater(() -> {
textarea.appendText(new Date() + " " + text + "\n");
});
}
} catch (IOException e) {
textarea.appendText("Error " + e + " \n");
try {
this.socket.close();
} catch (IOException ex) {
textarea.appendText("Error " + e + " \n");
}
e.printStackTrace();
}
}
}
public static void main(String[] args) { //The keyword void simply tells the compiler that main( ) does not return a value.
launch(args);
}
}
我能够向连接到服务器的客户端发送消息,但是当
- 当 Client Bunny 向 Joel 发送消息(接收消息)时,反之亦然。
- 当Bunny第二次给Joel发消息时(没有收到消息)。
如何再次迭代哈希表循环以发送和接收消息。
服务器Class
import java.io.*; //Input and output to read and write data.
import java.net.*; //serversocket and initaddress
import java.util.Date; //to get date
import java.util.Enumeration; //enumeration
import java.util.Hashtable; // hashtable
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javafx.application.Application; //
import javafx.application.Platform; //platformrun later to append text
import javafx.event.EventHandler; // on click actions
import javafx.geometry.Insets; //insets
import javafx.geometry.Pos; //position
import javafx.scene.Scene; //scene
import javafx.scene.control.TextArea; //textarea
import javafx.scene.layout.StackPane; //stackpane
import javafx.stage.Stage; //stage
import javafx.stage.WindowEvent; //event close
public class Server extends Application { //class server
static InetAddress inetAddress; //inetaddress
private final Hashtable<Object, Object> outputStreams = new Hashtable(); //hashtable
TextArea textarea = new TextArea(); //textarea
static DataInputStream inputFromClient = null; //datainputstream
static DataOutputStream outputToClient = null; //dataoutputstream
static int clientNo = 0; //client connected
static ServerSocket serverSocket; //server socket
Hashtable<Object, Object> hmap = new Hashtable<>();
@Override // Override the start method in the Application class
public void start(Stage primaryStage) { //Stage to show everything
StackPane root = new StackPane(); //root add all the elements
root.setPadding(new Insets(10, 10, 10, 10)); //padding
root.setAlignment(textarea, Pos.CENTER); //positioning textarea to center
textarea.setMaxSize(400, 400); //maxsize of textarea
textarea.setWrapText(true); //wraptext for the textarea
new Thread(() -> { //thread to hold the server for the connections
try {
// Create a server socket
ServerSocket serverSocket = new ServerSocket(8001); //The server creates a server socket and, once a connection to a client is established, connects to the client with a client socket.
textarea.appendText("MultiThreadServer started at " + new Date() + '\n'); //server started with date.
while (true) { //accept multiple connections
// Listen for a new connection request
Socket socket = serverSocket.accept(); //listening for new connection from server port.
// inputFromClient = new DataInputStream(socket.getInputStream());
outputToClient = new DataOutputStream(socket.getOutputStream()); //outputstream to output to client
// Increment clientNo
clientNo++;
Platform.runLater(() -> {
// Display the client number
textarea.appendText("Starting thread for client " + clientNo + " at " + new Date() + '\n');
// Find the client's host name, and IP address
InetAddress inetAddress = socket.getInetAddress();
textarea.appendText("Client " + clientNo + "'s host name is " + inetAddress.getHostName() + "\n");
textarea.appendText("Client " + clientNo + "'s IP Address is " + inetAddress.getHostAddress() + "\n");
});
HandleAClient hd = new HandleAClient(socket);
hmap.put(socket, outputToClient);
hd.start();
// outputStreams.put(socket, outputToClient); //using hashtable to store client socket and outputstream
// Create and start a new thread for the connection
// new HandleAClient(this, socket);
}
} catch (IOException ex) {
textarea.appendText(ex + " \n");
}
}).start();
root.getChildren().addAll(textarea); // add UI elements to the root
Scene scene = new Scene(root, 450, 400); // creating scene of size 450 width and height 500
primaryStage.setTitle("Server"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() { //close scene
@Override
public void handle(WindowEvent t) {
primaryStage.close();
Platform.exit();
System.exit(0);
}
});
}
// Used to get the output streams
Enumeration getOutputStreams() {
return outputStreams.elements();
}
// Used to send message to all clients
void sendToAll(String message) {
// Go through hashtable and send message to each output stream
for (Enumeration e = getOutputStreams(); e.hasMoreElements();) {
DataOutputStream dout = (DataOutputStream) e.nextElement();
try {
// Write message
dout.writeUTF(message);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
class HandleAClient extends Thread {
private Socket socket; // A connected socket
private String text = "";
/**
* Construct a thread
*/
public HandleAClient(Socket socket) throws IOException {
this.socket = socket;
}
/**
* Run a thread
*/
public void run() {
try {
// Create data input stream
inputFromClient = new DataInputStream(socket.getInputStream()); //receive input from client
textarea.appendText(new Date() + " Connection from " + socket + "\n");//showing connection from client
text = inputFromClient.readUTF(); // read string or message from client
// serversocket.sendToAll(text);
Set set = hmap.entrySet();
Iterator it = set.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
System.out.println("key " + entry.getKey() + " : " + entry.getValue());
DataOutputStream dout = (DataOutputStream) entry.getValue();
dout.writeUTF(text);
dout.flush();
}
Platform.runLater(() -> {
textarea.appendText(new Date() + " " + text + "\n");//append text
});
} catch (IOException e) {
textarea.appendText("Error " + e + " \n");
try {
this.socket.close(); //socket close
} catch (IOException ex) {
textarea.appendText("Error " + e + " \n");
}
e.printStackTrace();
}
}
}
public static void main(String[] args) { //The keyword void simply tells the compiler that main( ) does not return a value.
launch(args);
}
}
Client Class
import java.io.*; //Input and output to read and write data.
import java.net.*; //serversocket and initaddress
import javafx.application.Application; //
import javafx.application.Platform; //platformrun later to append text
import javafx.event.EventHandler; // on click actions
import javafx.geometry.Insets; //insets
import javafx.geometry.Pos; //position
import javafx.scene.Scene; //scene
import javafx.scene.control.TextArea; //textarea
import javafx.scene.layout.StackPane; //stackpane
import javafx.stage.Stage; //stage
import javafx.stage.WindowEvent; //event close
import javafx.scene.control.Button; // button
import javafx.scene.control.Label; //label
import javafx.scene.control.TextField; //textfield
public class Client extends Application {
// IO streams
static DataOutputStream toServer = null; //datainputstream
static DataInputStream fromServer = null; //dataoutputstream
Label usernamelabel = new Label("Set your name :"); //set name label
Label textarealabel = new Label("Type your message in the textarea"); //text label
Label textlabel = new Label("Enter Text :"); //enter text
TextField textfield = new TextField(); //textfield
TextField namefield = new TextField(); //name field
Button send = new Button("Send"); //sendbutton
TextArea messagefield = new TextArea(); //textarea
static ServerSocket serverSocket; //serversocket
// Override the start method in the Application class
public void start(Stage primaryStage) throws IOException {
StackPane root = new StackPane(); //stacpane
root.setPadding(new Insets(10, 10, 10, 10));
StackPane.setAlignment(usernamelabel, Pos.TOP_LEFT);
namefield.setMaxWidth(200);
StackPane.setAlignment(namefield, Pos.TOP_CENTER);
StackPane.setMargin(textlabel, new Insets(30, 0, 0, 0));
StackPane.setMargin(textfield, new Insets(30, 0, 0, 0));
StackPane.setAlignment(textlabel, Pos.TOP_LEFT);
textfield.setMaxWidth(200);
StackPane.setAlignment(textfield, Pos.TOP_CENTER);
StackPane.setAlignment(send, Pos.BOTTOM_CENTER);
messagefield.setMaxSize(450, 250);
StackPane.setAlignment(textarealabel, Pos.BOTTOM_CENTER);
StackPane.setMargin(textarealabel, new Insets(0, 0, 35, 0));
StackPane.setAlignment(messagefield, Pos.CENTER);
root.getChildren().addAll(usernamelabel, namefield, send, messagefield, textarealabel, textlabel, textfield); //adding all the UI elements
// Create a scene and place it in the stage
Scene scene = new Scene(root, 500, 400);
primaryStage.setTitle("Client"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
send.setOnAction(e -> { //send button action
try {
if (namefield.getText().trim().length() == 0) { //name field is empty
messagefield.appendText("Name field is empty. Please enter your name\n");
} else if (textfield.getText().trim().length() == 0) { //message field is empty
messagefield.appendText("Message field is empty. Please enter your message to send\n");
}
// Send the radius to the server
if (namefield.getText().trim().length() > 0 && textfield.getText().trim().length() > 0) {
toServer.writeUTF(namefield.getText().trim() + " : " + textfield.getText().trim());
toServer.flush();
}
} catch (IOException ex) {
messagefield.appendText(ex+" \n");
}
});
try {
// Create a socket to connect to the server
Socket socket = new Socket("localhost", 8001); //socket with port number to connect server
// Create an output stream to send data to the server
toServer = new DataOutputStream(socket.getOutputStream());
new ReceiveMessage(socket); // send socket receieve class
// }
} catch (Exception ex) {
messagefield.setText(ex.toString() + '\n');
}
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() { //scene close
@Override
public void handle(WindowEvent t) {
Platform.exit();
System.exit(0);
}
});
}
class ReceiveMessage implements Runnable { //class receive message
private final Socket socket;//socket
public ReceiveMessage(Socket socket) { // constructor
this.socket = socket; //socket intializes
Thread thread = new Thread(this);
thread.setDaemon(true);
thread.start();
}
public void run() {
try {
fromServer = new DataInputStream(socket.getInputStream()); //to read from server
while (true) { // to continously receieve messages
// Get area from the server
String textmessage = fromServer.readUTF(); //read message from server
toServer.flush(); // flush
Platform.runLater(() -> {
messagefield.appendText(textmessage + " \n"); //append to textarea
});
}
} catch (IOException e) {
messagefield.appendText("Error " + e);
}
}
}
public static void main(String[] args) { //The keyword void simply tells the compiler that main( ) does not return a value.
launch(args);
}
}
服务器 class 已执行并占用客户端
客户端一已连接
客户端二连
谢谢。
我在代码中犯的错误是在客户端向服务器发送消息并在服务器连接暂停或停止后向所有连接到服务器的客户端发送消息我不知道为什么。我使用枚举方法向连接到服务器的所有客户端发送消息。这就是我解决问题的方法。希望我的回答对尝试使用线程实现客户端-服务器(多客户端)聊天应用程序的人有所帮助。
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class Server extends Application {
static InetAddress inetAddress;
private final Hashtable<Object, Object> outputStreams = new Hashtable();
TextArea textarea = new TextArea();
static int clientNo = 0;
static ServerSocket serverSocket;
Hashtable<Object, Object> hmap = new Hashtable<>();
ArrayList<Object> clients = new ArrayList<Object>();
public void start(Stage primaryStage) {
StackPane root = new StackPane();
root.setPadding(new Insets(10, 10, 10, 10));
root.setAlignment(textarea, Pos.CENTER);
textarea.setMaxSize(400, 400);
textarea.setWrapText(true);
root.getChildren().addAll(textarea);
Scene scene = new Scene(root, 450, 400);
primaryStage.setTitle("Server");
primaryStage.setScene(scene);
primaryStage.show(); // Display the stage
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent t) {
primaryStage.close();
Platform.exit();
System.exit(0);
}
});
new Thread(() -> {
listen();
}).start();
}
private void listen() {
try {
// Create a server socket
serverSocket = new ServerSocket(8001);
textarea.appendText("MultiThreadServer started at " + new Date() + '\n');
while (true) {
Socket socket = serverSocket.accept();
inputFromClient = new DataInputStream(socket.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
clientNo++;
Platform.runLater(() -> {
textarea.appendText("Starting thread for client " + clientNo + " at " + new Date() + '\n');
InetAddress inetAddress = socket.getInetAddress();
textarea.appendText("Client " + clientNo + "'s host name is " + inetAddress.getHostName() + "\n");
textarea.appendText("Client " + clientNo + "'s IP Address is " + inetAddress.getHostAddress() + "\n");
});
hmap.put(socket, outputToClient);
new HandleAClient(socket);
}
} catch (IOException ex) {
textarea.appendText(ex + " \n");
}
}
Enumeration getOutputStreams() {
return hmap.elements();
}
void sendToAll(String message) {
for (Enumeration e = getOutputStreams(); e.hasMoreElements();) {
DataOutputStream dout = (DataOutputStream) e.nextElement();
try {
dout.writeUTF(message);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
void All(String text) throws IOException {
Set set = hmap.entrySet();
Iterator it = set.iterator();
System.out.println("Text " + text);
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
System.out.println("key " + entry.getKey() + " : " + entry.getValue());
DataOutputStream dout = (DataOutputStream) entry.getValue();
dout.writeUTF(text);
dout.flush();
}
}
class HandleAClient extends Thread {
private final Socket socket; // A connected socket
private String text = "";
/**
* Construct a thread
*/
public HandleAClient(Socket socket) throws IOException {
this.socket = socket;
start();
}
/**
* Run a thread
*/
public void run() {
try {
DataInputStream inputFromClient = new DataInputStream(socket.getInputStream()); //receive input from client
while (true) {
textarea.appendText(new Date() + " Connection from " + socket + "\n");
text = inputFromClient.readUTF();
serversocket.sendToAll(text);
All(text);
Platform.runLater(() -> {
textarea.appendText(new Date() + " " + text + "\n");
});
}
} catch (IOException e) {
textarea.appendText("Error " + e + " \n");
try {
this.socket.close();
} catch (IOException ex) {
textarea.appendText("Error " + e + " \n");
}
e.printStackTrace();
}
}
}
public static void main(String[] args) { //The keyword void simply tells the compiler that main( ) does not return a value.
launch(args);
}
}