如何在特定时间间隔从服务器向客户端发送Web套接字消息?

时间:2019-06-04 06:22:10

标签: scala websocket akka play-framework-2.7

我已经使用Play Framework实现了Web套接字服务器。服务器可以建立连接并响应客户端。 如果连接空闲了一段时间,则服务器会自动关闭连接。 我不确定是否有任何配置可以使连接始终保持活动状态。 因此,为了监视连接状态(连接是否存在),服务器需要在特定时间向客户端发送PING消息 间隔,它应该从客户端收到PONG。

下面是我的服务器实现

@Singleton
class RequestController @Inject()(cc: ControllerComponents)(implicit system: ActorSystem, mat: Materializer) extends AbstractController(cc) {
    def ws = WebSocket.accept[String, String] {req =>
    ActorFlow.actorRef { out =>
      ParentActor.props(out)
    }
  }
}

object ParentActor {
  def props(out: ActorRef) = Props(new ParentActor(out))
}

class ParentActor(out : ActorRef) extends Actor {
    override def receive: Receive = {
         case msg: String => out ! s"Echo from server $msg"
    }
}

那么如何在特定时间间隔从服务器向客户端发送Web套接字ping消息?

1 个答案:

答案 0 :(得分:0)

您可以使用调度程序,以便在一定间隔内将消息发送到客户端。以下是可用于实现方案的示例之一:

  class ParentActor(out : ActorRef) extends Actor {
    var isPongReceived = false
    override def receive: Receive = {
      case "START" => 
        // Client started the connection, i.e. so, initially let mark client pong receive status as true. 
        isPongReceived = true
        out ! s"Echo from server - Connection Started"

        // This part schedules a scheduler that check in every 10 seconds if client is active/connected or not. 
        // Sends PING response if connected to client, otherwise terminate the actor. 
        context.system.scheduler.schedule(new DurationInt(10).seconds,
          new DurationInt(10).seconds) {
          if(isPongReceived) {
            // Below ensures that server is waiting for client's PONG message in order to keep connection. 
            // That means, next time when this scheduler run after 10 seconds, if PONG is not received from client, the
            // connection will be terminated. 
            isPongReceived = false   
            out ! "PING_RESPONSE"
          }
          else {
            // Pong is not received from client / client is idle, terminate the connection.
            out ! PoisonPill  // Or directly terminate - context.stop(out)
          }
        }
      case "PONG" => isPongReceived = true  // Client sends PONG request, isPongReceived status is marked as true. 
    }
  }