2017-12-17 24 views
0

localhost의 websocket을 통해 일부 서버에 연결하려고합니다. 내가 JS에서 그것을하려고 할 때Akka-http : localhost의 websocket에 연결

ws = new WebSocket('ws://localhost:8137'); 

그것은 성공한다. 그러나 akka-http 및 akka-streams을 사용하면 "연결에 실패했습니다"라는 오류가 발생합니다.

object Transmitter { 
    implicit val system: ActorSystem = ActorSystem() 
    implicit val materializer: ActorMaterializer = ActorMaterializer() 

    import system.dispatcher 

    object Rec extends Actor { 
     override def receive: Receive = { 
      case TextMessage.Strict(msg) => 
       Log.info("Recevied signal " + msg) 
     } 
    } 

    // val host = "ws://echo.websocket.org" 
    val host = "ws://localhost:8137" 

    val sink: Sink[Message, NotUsed] = Sink.actorRef[Message](system.actorOf(Props(Rec)), PoisonPill) 


    val source: Source[Message, NotUsed] = Source(List("test1", "test2") map (TextMessage(_))) 


    val flow: Flow[Message, Message, Future[WebSocketUpgradeResponse]] = 
     Http().webSocketClientFlow(WebSocketRequest(host)) 

    val (upgradeResponse, closed) = 
     source 
     .viaMat(flow)(Keep.right) // keep the materialized Future[WebSocketUpgradeResponse] 
     .toMat(sink)(Keep.both) // also keep the Future[Done] 
     .run() 

    val connected: Future[Done.type] = upgradeResponse.flatMap { upgrade => 
     if (upgrade.response.status == StatusCodes.SwitchingProtocols) { 
      Future.successful(Done) 
     } else { 
      Future.failed(new Exception(s"Connection failed: ${upgrade.response.status}") 
     } 
    } 

    def test(): Unit = { 
     connected.onComplete(Log.info) 
    } 
} 

ws : //echo.websocket.org에서 완전히 작동합니다.

자바 스크립트 클라이언트에서 작동하고 문제가 연결에만 적용되기 때문에 제 서버의 코드를 추가하는 것이 적절하다고 생각합니다.

내가 뭘 잘못하고 있니?

답변

0

해결책을 찾았습니다. 사용하는 서버가 IPv6 (as :: 1)에서 실행 중이지만 akka-http는 localhost를 127.0.0.1로 취급하고 :: 1을 무시합니다. IPv4를 사용하도록 강제로 서버를 다시 작성해야만했습니다.

1

akka documentation, 에서 websocket 서버로 클라이언트 구현을 테스트했지만 연결 오류가 발생하지 않았습니다. websocket 클라이언트가 성공적으로 연결됩니다. 그래서 내가 문제를 서버 구현과 함께 추측하고 있습니다.

object WebSocketServer extends App { 
    implicit val system = ActorSystem() 
    implicit val materializer = ActorMaterializer() 
    import Directives._ 

    val greeterWebSocketService = Flow[Message].collect { 
    case tm: TextMessage => TextMessage(Source.single("Hello ") ++ tm.textStream) 
    } 

    val route = 
    get { 
     handleWebSocketMessages(greeterWebSocketService) 
    } 

    val bindingFuture = Http().bindAndHandle(route, "localhost", 8137) 

    println(s"Server online at http://localhost:8137/\nPress RETURN to stop...") 
    StdIn.readLine() 

    import system.dispatcher // for the future transformations 
    bindingFuture 
    .flatMap(_.unbind()) // trigger unbinding from the port 
    .onComplete(_ => system.terminate()) // and shutdown when done 
} 

그런데 배우의 수신 방법이 가능한 모든 메시지를 다루지 않는 것으로 나타났습니다. that akka issue에 따르면 모든 메시지는 매우 작아도 Streamed으로 끝날 수 있습니다. 모든 문자 메시지를 인쇄하려면 배우의 더 나은 구현은 다음과 같습니다

object Rec extends Actor { 
    override def receive: Receive = { 
    case TextMessage.Strict(text)    ⇒ println(s"Received signal $text") 
    case TextMessage.Streamed(textStream)  ⇒ textStream.runFold("")(_ + _).foreach(msg => println(s"Received streamed signal: $msg")) 
    } 
} 

my github에 작업 프로젝트를 찾아주세요.

+0

감사합니다. 그것은 정확하게 내 질문에 대답하지 않았지만, 나는 당신의 서버를 시작했을 때, 다른 하나는 여전히 실행중인 것으로 나타났습니다. 예, 정확한 항구에 있습니다. 한 가지는 127.0.0.1에서 실행되었고 다른 하나는 :: 1에서 실행되었습니다. – Ikciwor

+0

예제에서 들어오는 스트리밍 된 메시지를 그런 식으로 구체화하려면 차단하지 않았습니까? – kyle