2016-12-01 13 views
5

Tôi đang làm việc trên trò chơi mulitplayer đơn giản trong scala mà tôi muốn hiển thị thông qua websockets cho các máy khách JS.Akka HTTP Websocket, cách xác định các kết nối bên trong của diễn viên

Đây là lớp WebsocketServer tôi

class WebsocketServer(actorRef: ActorRef, protocol: Protocol, system: ActorSystem, materializer: ActorMaterializer) extends Directives { 

    val route = get { 
     pathEndOrSingleSlash { 
     handleWebSocketMessages(websocketFlow) 
     } 
    } 

    def websocketFlow: Flow[Message, Message, Any] = 
     Flow[Message] 
     .map { 
      case TextMessage.Strict(textMessage) => protocol.hydrate(textMessage) 
     } 
     .via(actorFlow) 
     .map(event => TextMessage.Strict(protocol.serialize(event))) 


    def actorFlow : Flow[Protocol.Message, Protocol.Event, Any] = { 
     val sink = 
     Flow[Protocol.Message] 
      .to(Sink.actorRef[Protocol.Message](actorRef, Protocol.CloseConnection())) 

     val source = 
     Source.actorRef[Protocol.Event](1, OverflowStrategy.fail) 
      .mapMaterializedValue(actor => actorRef ! Protocol.OpenConnection(actor)) 

     Flow.fromSinkAndSource(sink, source) 
    } 
} 

này được đơn giản hóa mã của nam diễn viên của tôi rằng sẽ nhận được tin nhắn từ máy chủ WebSocket.

class GameActor() extends Actor { 

    private var connections: List[ActorRef] = List() 

    override def receive: Receive = { 

    case message: Protocol.OpenConnection => { 
     this.connections = message.connection :: this.connections 
     message.connection ! Protocol.ConnectionEstablished() 
    } 

    case message: Protocol.CloseConnection => { 
     // how can I remove actor from this.connections ? 
    } 

    case message: Protocol.DoSomething => { 
     // how can I identify from which connection this message came in? 
    } 
    } 
} 

Cho đến nay rất tốt, hiện nay tôi có thể đáp ứng với WelcomeMessage đơn giản với một khách hàng tuy nhiên tôi vẫn không biết làm thế nào để: diễn viên

  • loại bỏ ra khỏi danh sách các kết nối bất cứ khi nào diễn viên nhận CloseConnection thông điệp?
  • xác định từ đó thông báo kết nối đến với diễn viên?

Trả lời

2

Tôi nghĩ bạn cần có một số loại key hoặc id để ánh xạ với diễn viên kết nối của bạn.

khi đó trong diễn viên, bạn có thể lưu trữ kết nối trong Bản đồ thay vì Danh sách, điều này cũng có hiệu quả hơn khi xóa.

+1

Tôi đang tìm một loại cơ chế tích hợp và không bao giờ nghĩ về giải pháp đơn giản nhất, cảm ơn! –

2

Câu hỏi này đã được trả lời. Đối với những người Java ra khỏi đó, đây là phiên bản java:

public class WebsocketRoutes extends AllDirectives { 

private final ActorSystem actorSystem; 
private final ActorRef connectionManager; 

public WebsocketRoutes(final ActorSystem actorSystem, final ActorRef connectionManager) { 
    this.actorSystem = actorSystem; 
    this.connectionManager = connectionManager; 
} 

public Route handleWebsocket() { 
    return path(PathMatchers.segment(compile("router_v\\d+")).slash(PathMatchers.segment("websocket")).slash(PathMatchers.segment(compile("[^\\\\/\\s]+"))), (version, routerId) -> 
      handleWebSocketMessages(createWebsocketFlow(routerId)) 
    ); 
} 

private Flow<Message, Message, NotUsed> createWebsocketFlow(final String routerId) { 

    final ActorRef connection = actorSystem.actorOf(WebsocketConnectionActor.props(connectionManager)); 

    final Source<Message, NotUsed> source = Source.<RouterWireMessage.Outbound>actorRef(5, OverflowStrategy.fail()) 
      .map((outbound) -> (Message) TextMessage.create(new String(outbound.message, "utf-8"))) 
      .throttle(5, FiniteDuration.create(1, TimeUnit.SECONDS), 10, ThrottleMode.shaping()) 
      .mapMaterializedValue(destinationRef -> { 
       connection.tell(new RouterConnected(routerId, destinationRef), ActorRef.noSender()); 
       return NotUsed.getInstance(); 
      }); 

    final Sink<Message, NotUsed> sink = Flow.<Message>create() 
      .map((inbound) -> new RouterWireMessage.Inbound(inbound.asTextMessage().getStrictText().getBytes())) 
      .throttle(5, FiniteDuration.create(1, TimeUnit.SECONDS), 10, ThrottleMode.shaping()) 
      .to(Sink.actorRef(connection, PoisonPill.getInstance())); 

    return Flow.fromSinkAndSource(sink, source); 
} 
} 
Các vấn đề liên quan