我能够向连接到服务器的客户端发送消息,但是
如何再次迭代哈希表循环以发送和接收消息。
服务器类
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);
}
}
服务器类已执行并接受客户端
客户端一连接
客户端两个已连接
谢谢。
答案 0 :(得分:0)
我在代码中犯的错误是在客户端将消息发送到服务器并将消息发送到连接到该服务器的所有客户端之后,该服务器连接被暂停或暂停后,我不知道为什么。我使用枚举方法将消息发送到连接到服务器的所有客户端。这就是我解决问题的方式。希望我的回答对尝试使用线程实现客户端-服务器(多个客户端)聊天应用程序的人有所帮助。
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);
}
}