我对Java比较新,我在创建多客户端/服务器聊天时遇到问题。
我需要将服务器实现到可以从一个或多个客户端接收多条消息的位置,并将所有这些消息发送到所有客户端。所以,假设有两个客户端,client1将消息“hi”发送给服务器。服务器会将该消息发送到client1和client2(它会对连接到服务器的所有可能的客户端进行发回)。
另外,如何将客户的用户名与他们的消息相关联?如果client1发送“hi”,我希望Client1和Client2中显示消息的TextAreas说“client1:hi”。
实现在JavaFX中完成。
服务器代码:
package server;
import java.io.*;
import java.net.*;
import java.util.*;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextArea;
public class ServerFormController implements Initializable{
@FXML
public TextArea svrLog;
private int clientNo = 0;
ArrayList<HandleAClient> clients = new ArrayList<>();
//@Override
// public void run()
// {
// }
@Override
public void initialize(URL url, ResourceBundle rb) {
new Thread( () ->
{
try{
ServerSocket serverSocket = new ServerSocket(8000);
svrLog.appendText("Server started at " + new Date() + '\n');
while (true)
{
Socket socket = serverSocket.accept();
svrLog.appendText("Worked \n");
clientNo++;
//svrLog.appendText("Starting thread for client " + clientNo + "at"
// + new Date() + '\n');
// InetAddress inetAddress = socket.getInetAddress();
//svrLog.appendText("Client " + clientNo + "'s host name is "
//+ inetAddress.getHostName() + "\n");
// svrLog.appendText("Client " + clientNo + "'s IP Address is "
// + inetAddress.getHostAddress() + "\n");
new Thread(new HandleAClient(socket)).start();
}
} catch (IOException ex) {
svrLog.appendText("Couldn't create ServerSocket! \n");
}
}).start();
}
/** Creates individual client socket*/
class HandleAClient implements Runnable {
private Socket socket;
DataInputStream inputFromClient = null;
DataOutputStream outputToClient = null;
//ServerFormController svr;
public HandleAClient(Socket socket)
{
this.socket = socket;
}
public void run()
{
try{
inputFromClient = new DataInputStream(socket.getInputStream());
outputToClient = new DataOutputStream(socket.getOutputStream());
while (true)
{
String msg = inputFromClient.readUTF();
// for(int i = 0; i < clients.size(); i++) // probably because object in client contain null datastreams
// clients.get(i).outputToClient.writeUTF(msg); // nope.
outputToClient.writeUTF(msg);
svrLog.appendText(msg);
svrLog.appendText("New message received from client. Sent to all clients.");
}
} catch (IOException ex) {
svrLog.appendText("Could not create data stream with client! \n");
}
}
}
}
客户代码:
package handlerclient;
import java.io.*;
import java.net.*;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
public class HandlerClientFormController implements Initializable {
@FXML
private TextField ipAdrText; // TextField to get the IP Address
@FXML
private TextField usernameText; // TextField to get the user's chat name
@FXML
private Button clientConnectBtn; // Tries to connect to server
@FXML
private TextArea msgLogTxtArea; // Displays all the messages between the clients
@FXML
private TextArea msgSendTxtArea; // TextArea to get the message from the client
@FXML
private Button clientSendBtn; // Sends the message from the client to the server
DataOutputStream toServer = null;
DataInputStream fromServer = null;
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
@FXML
private void onConnectBtnClick(ActionEvent event) {
try{
Socket socket = new Socket(ipAdrText.getText(), 8000);
fromServer = new DataInputStream(socket.getInputStream());
toServer = new DataOutputStream(socket.getOutputStream());
}
catch (IOException ex)
{
msgLogTxtArea.appendText("Could not connect to server!");
}
}
@FXML
private void onSendBtnClick(ActionEvent event) {
try{
toServer.writeUTF(msgSendTxtArea.getText());
toServer.flush();
String newmsg = fromServer.readUTF();
msgLogTxtArea.appendText(newmsg + '\n');
}
catch (IOException ex)
{
msgLogTxtArea.appendText("Could not send/receive message! \n");
}
}
}
答案 0 :(得分:0)
例如,可以通过扩展HandleAClient的构造函数来完成。
想法 - 保存客户端处理程序客户端的信息。
在创建HandleAClient实例时,在ServerFormController中,我们有关于客户端号码的信息。
我们可以将它作为构造函数的附加参数提供给HandleAClient,因此当客户端处理程序从客户端接收消息时,它将能够进行个性化的操作。带有具体客户名称的消息。