1

私は古い学校のテキスト ベースの telnet サーバーを作成していますが、これは現在、Akka アクター ベースの IO を備えた Scala の栄光のチャット ルームです。何が起こっているかというと、クライアントが何かを入力し始めると、イベントが発生し、それが書き込まれると、既に入力されたものはすべて消去されます。次の例では、Tom が「say How are you?」と入力し始めています。しかし、フレッドは「say How ar」と入力しただけで到着し、この入力は消去されます。

Tom > say How ar
Fred has arrived.
Tom > 

まだフラッシュされていない出力バッファを telnet に再表示させる方法はありますか?

サーバーは次のとおりです。

class TcpServer(port: Int) extends Actor {
  import TcpServer._
  import context.system

  val log = Logging(system, this)
  var connectionNum: Int = 1

  log.info(STARTING_SERVER)

  IO(Tcp) ! Bind(self, new InetSocketAddress("0.0.0.0", port))

  def receive = {
    case b @ Bound(localAddress) =>
      log.info(PORT_BOUND, localAddress)
    case c @ Connected(remote, local) =>
      log.info(CONNECTION_ACCEPTED)
      context.actorOf(ConnectionHandler.connectionProps(sender()), s"conn$connectionNum")
      connectionNum += 1
    case CommandFailed(_: Bind) =>
      log.error(BINDING_FAILED)
      context stop self
  }
}

以下は、ConnectionHandler、そのコンパニオン オブジェクト、およびそれが使用するメッセージ ケース クラスです。

class ConnectionHandler(connection: ActorRef) extends Actor {
  import context._

  val log = Logging(context.system, this)

  connection ! Register(self)

  var delegate = actorOf(Props[LoginHandler], "login")
  watch(delegate)

  def receive = {
    case Received(data) =>
      val dataString = data.utf8String.trim
      log.info("Received data from connection: {}", dataString)
      delegate ! Input(dataString)

    case Output(content) =>
      connection ! Write(ByteString(content))

    case LoggedIn(user) =>
      unwatch(delegate)
      delegate ! PoisonPill

      delegate = actorOf(UserHandler.connectionProps(user), user.name.toLowerCase)
      watch(delegate)

    case Terminated =>
      log.warning("User delegate died unexpectedly.")
      connection ! ConfirmedClose

    case CloseConnection(message) =>
      connection ! Write(ByteString(message + "\n"))
      connection ! ConfirmedClose
      log.info("User quit.")

    case ConfirmedClosed =>
      log.info("Connection closed.")
      stop(self)

    case PeerClosed =>
      log.info("Connection closed by client.")
      stop(self)
  }
}

object ConnectionHandler {
  def connectionProps(connection: ActorRef): Props = Props(new ConnectionHandler(connection))
}

case class Input(input: String)
case class Output(output: String)
case class LoggedIn(user: User)
case class CloseConnection(message: String)
4

1 に答える 1