首页 文章

服务器向客户端发送消息

提问于
浏览
1

我是Java的新手,我在创建多客户端/服务器聊天时遇到了问题 .

我需要将服务器实现到可以从一个或多个客户端接收多条消息的位置,并将所有这些消息发送到所有客户端 . 所以,假设有两个客户端,client1将消息"hi"发送到服务器 . 服务器将该消息发送到client1和client2(它对所有可能连接到服务器的 clients 执行 send back ) .

另外,如何将客户端的用户名与其消息相关联?如果client1发送“hi”,我希望Client1和Client2中显示消息的TextAreas说“client1:hi” .

实现在JavaFX中完成 .

Server code:

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

Client code:

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

}

1 回答

  • 0

    例如,可以通过扩展HandleAClient的构造函数来完成 .
    想法 - 保存客户端处理程序客户端的信息 .
    在您的ServerFormController中创建HandleAClient 's instance we have information about client'的号码 . 我们可以将它作为构造函数的附加参数提供给HandleAClient,因此当客户端处理程序从客户端接收消息时,它将能够使用具体客户端的名称生成'personalized'消息 .

相关问题