如何在此Java代码之上添加心跳消息(用于KnockKnockClient/Server)?

2022-09-01 08:50:41

我正在研究以下基本的Java套接字代码(源代码)。这是一个Knock-Knock-Joke客户端/服务器应用程序。

客户端中,我们像往常一样设置套接字:

try {
  kkSocket = new Socket("localhost", 4444);
  out = new PrintWriter(kkSocket.getOutputStream(), true);
  in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));
} catch( UnknownHostException uhe ){ /*...more error catching */

然后,我们只是读取和写入服务器:

BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer;
String fromUser;

while ((fromServer = in.readLine()) != null) {
  System.out.println("Server: " + fromServer);
  if (fromServer.equals("bye."))
      break;

  fromUser = stdIn.readLine();

  if (fromUser != null){
      System.out.println("Client: " + fromUser);
      out.println(fromUser);
  }

而在服务器上,我们有相应的代码,拿到笑话的打卡线。

    KnockKnockProtocol kkp = new KnockKnockProtocol();

    outputLine = kkp.processInput(null);
    out.println(outputLine);

    while ((inputLine = in.readLine()) != null) {
         outputLine = kkp.processInput(inputLine);
         out.println(outputLine);
         if (outputLine.equals("Bye."))
            break;

我想将心跳附加到整个事物上,每当检测到另一方死亡时,它将打印到控制台上。因为如果我杀死另一方,现在会发生什么是一个例外 - 就像下面这个:

enter image description here

因此,如果我同时运行KnockKnockClient和KnockKnockServer,那么我关闭了KnockKnockServer,应该发生的事情是,在客户端上我看到这个输出:

>The system has detected that KnockKnockServer was aborted

我正在寻找任何提示。到目前为止,我主要尝试运行一个守护进程线程,该线程会定期创建到另一端的新连接。但是我对检查什么条件感到困惑(但我认为这只是一个值?这是正确的方法吗?我刚刚在网上发现有一个名为JGroups的用于多播网络的库 - 这会是一个更好的方法吗?我正在寻找任何提示。boolean

到目前为止,我的服务器代码(抱歉它很乱)

&

客户端

谢谢


答案 1

但是你得到的例外正是这个!它告诉你,另一方刚刚死了。只需捕获异常并打印到控制台,即“系统已检测到KnockKnockServer已中止”。

您正在使用 TCP 连接,并且 TCP 具有内置的检测信号(保持活动)机制,该机制将为您执行此操作。只需在套接字上设置 setKeepAlive() 即可。话虽如此 - 可以控制每个连接的保持活动频率,但我不知道如何在java中执行此操作。

http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html

https://stackoverflow.com/a/1480259/706650


答案 2

您有同步通信。要获得检测信号消息,请使用异步通信。将有 2 个线程。一个将从套接字读取,另一个将继续写入套接字。如果使用异步通信,服务器将每 10 秒发送一条消息。客户端线程将从服务器读取消息,如果没有消息,则表示服务器已关闭。在您的情况下,服务器要么将消息发回客户端(如果客户端有一些消息),要么发送自动回复。您的服务器代码可以像这样修改。

  1. 创建一个服务器线程,该线程将每 10 秒向客户端发送一次消息。

    public class receiver extends Thread{
    
      public static bool hearbeatmessage=true;
    
      Socket clientSocket=new Socket();
      PrintWriter out=new PrintWriter();
      public receiver(Socket clientsocket){
      clientSocket=clientsocket;
      out = new PrintWriter(clientSocket.getOutputStream(), true);
    }
    
      public void run(){
    
        while(true)
        {
    
          if(heartbeatmessage){
            thread.sleep(10000);
            out.println("heartbeat");
    
          }
        }            
      }
    }
    

在服务器代码中:

KnockKnockProtocol kkp = new KnockKnockProtocol();

outputLine = kkp.processInput(null);
out.println(outputLine);
receiver r=new reciver(clientSocket);
r.run(); /*it will start sending hearbeat messages to clients */

while ((inputLine = in.readLine()) != null) {
     outputLine = kkp.processInput(inputLine);
     reciver.hearbeatMessage=false; /* since you are going to send a message to client now, sending the heartbeat message is not necessary */
     out.println(outputLine);
     reciver.hearbeatMessage=true; /*start the loop again*/
     if (outputLine.equals("Bye."))
        break;

客户端代码也将被修改,线程将继续从套接字读取消息,如果它超过11秒(额外1秒)没有收到消息,它将声明服务器不可用。

希望这有帮助。逻辑上也可能有一些缺陷。让我知道。


推荐