2016-08-25 29 views
9

Pracuję nad projektem open source, Storj. Piszę klienta Java, który łączy się z backendem websocket Node.js. Klient korzysta z Tyrusa. Komunikat powinien udać się następująco:Klient sieci web Tyrus @OnMessage nigdy nie był wywoływany - Storj Projekt open source

  • Połącz
  • Klient wysyła żeton uwierzytelniający (tekst).
  • Serwer wysyła plik z powrotem (plik binarny).
  • Serwer zamyka połączenie.

Mam problemy, ponieważ moja wiadomość @OnMessage nigdy nie zostanie wywołana. Próbowałem z prostym klientem javascript online tutaj na ten sam URL i z tym samym tokenem: https://www.websocket.org/echo.html

Otrzymuję odpowiedź za pomocą tego, co mówi mi, że coś jest nie tak z projektem Java.

Przed pobraniem pliku, na wcześniejszym etapie, mogę przesłać plik bez żadnych problemów. Jednak ten krok nie wymaga wywołania funkcji @OnMessage (po prostu powoduje przesłanie pliku, a następnie serwer rozłącza się z wiadomością), więc nie jestem pewien, czy moja wiadomość @OnMessage jest zawsze aktywna.

Oto odpowiedni kod dla websocket (dostępne także na Github): https://github.com/NutterzUK/storj-java-bridge-client/blob/master/storj-client/src/main/java/storj/io/client/websockets/WebsocketFileRetriever.java

package storj.io.client.websockets; 

import com.google.gson.Gson; 
import storj.io.restclient.model.FilePointer; 

import javax.websocket.*; 
import java.io.File; 
import java.io.IOException; 
import java.nio.ByteBuffer; 

import java.util.concurrent.CountDownLatch; 
import java.util.logging.Logger; 

/** 
* Created by steve on 12/07/2016. 
*/ 
@ClientEndpoint 
public class WebsocketFileRetriever { 

    private Logger logger = Logger.getLogger(this.getClass().getName()); 
    private Gson gson = new Gson(); 
    private FilePointer filePointer; 
    private File outputFile; 
    private AuthorizationModel authModel; 
    private CountDownLatch latch; 

    public WebsocketFileRetriever(FilePointer filePointer, File outputFile, CountDownLatch latch){ 
     this.filePointer = filePointer; 
     this.latch = latch; 
     this.outputFile = outputFile; 
     authModel = new AuthorizationModel(); 
     authModel.setToken(filePointer.getToken()); 
     authModel.setOperation(filePointer.getOperation()); 
     authModel.setHash(filePointer.getHash()); 
    } 

    @OnMessage 
    public void onMessage(String s){ 
     logger.info("Received ... " + s); 
    } 

    @OnMessage 
    public void onMessage(ByteBuffer message, Session session) { 
     logger.info("Received ...." + message); 
    } 

    @OnOpen 
    public void onOpen(Session session, EndpointConfig endpointConfig) { 
     logger.info("Opened"); 
     try { 
      session.getBasicRemote().sendText(gson.toJson(authModel), true); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     logger.info("sent: " + gson.toJson(authModel)); 
    } 

    @OnClose 
    public void onClose(Session session, CloseReason closeReason) { 
     logger.info("Closed Websocket: " + closeReason.getCloseCode() + " " + closeReason.getReasonPhrase()); 
     //latch.countDown(); 
    } 

    @OnError 
    public void onError(Session session, Throwable t) { 
     t.printStackTrace(); 
    } 
} 

I kod, który rozpoczyna ten websocket, dostępny tutaj https://github.com/NutterzUK/storj-java-bridge-client/blob/master/storj-client/src/main/java/storj/io/client/DefaultStorjClient.java:

 CountDownLatch latch; 
     latch = new CountDownLatch(1); 
     ClientManager wsClient = ClientManager.createClient(); 
     try { 
      wsClient.setDefaultMaxBinaryMessageBufferSize(Integer.MAX_VALUE); 
      wsClient.setDefaultMaxTextMessageBufferSize(Integer.MAX_VALUE); 
      logger.info("CONNECTING TO: " + "ws://" + pointer.getFarmer().getAddress() + ":" + pointer.getFarmer().getPort()); 
      final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build(); 

      wsClient.connectToServer(new WebsocketFileRetriever(pointer, encryptedOutputFile, latch), cec, new URI("ws://" + pointer.getFarmer().getAddress() + ":" + pointer.getFarmer().getPort())); 
      latch.await(); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 

I próbowałem również uaktualnić Tyrusa do najnowszej wersji i otrzymałem taki sam wynik. Jakieś pomysły?

Wyjście z tego kodu jest:

Aug 25, 2016 8:55:31 PM storj.io.client.DefaultStorjClient downloadFile 
INFO: CONNECTING TO: ws://164.storj.eu:8607 
Aug 25, 2016 8:55:35 PM storj.io.client.websockets.WebsocketFileRetriever onOpen 
INFO: Opened 
Aug 25, 2016 8:55:35 PM storj.io.client.websockets.WebsocketFileRetriever onOpen 
INFO: sent: {"token":"06c36d4bac4f07ee1751068b5b2230f22e884b38","hash":"837b79bec927a1d8fa7fedd2ea0bb276e0d86e0f","operation":"PULL"} 
Aug 25, 2016 8:56:11 PM storj.io.client.websockets.WebsocketFileRetriever onClose 
INFO: Closed Websocket: NORMAL_CLOSURE Closing 

Po wysłaniu wiadomości, że wisi na chwilę przed komunikatem „NORMAL_CLOSURE” z @OnClose.

Update: Naprawdę łatwy sposób uruchomić to odtworzyć problem

Dodałem nazwę użytkownika i hasło testowy do repozytorium git, więc kod dostępny jest tutaj: https://github.com/NutterzUK/storj-java-bridge-client

Aby uruchom go, wystarczy uruchomić storj.io.client.main.MainTest

Szybkie przejrzenie tego, co robi. Najpierw wyśle ​​trochę żądań HTTP, aby uzyskać token. Użyje tego tokena do połączenia się z czyjąś maszyną poprzez websocket, a ten token wyśle ​​jako tekst. W odpowiedzi powinien otrzymać plik jako bajty.

Zanim się połączy, wydrukuje token i adres, z którym ma się połączyć. Zawiesza się na chwilę przed zamknięciem i nie jest wywoływana żadna metoda onMessage. Do testowania, jeśli umieścisz tam plik System.exit (Uncomment Line 152 w DefaultStorjClient.java), to się nie połączy, więc możesz użyć tego tokena w innym kliencie. Przetestowałem używając https://www.websocket.org/echo.html (Upewnij się, że Twoja przeglądarka zezwala na niebezpieczne adresy URL, ponieważ nie jest to "wss", aby to zrobić, musisz kliknąć tarczę w prawym górnym rogu.Widzę, że serwer odpowiada: Image showing the blob being received

Pokazuje to, że obiekt blob jest rzeczywiście wysyłany w odpowiedzi na wiadomość tekstową, ale wiadomość @OnMessage w Tyrusie nigdy nie zostaje zwolniona.

+0

Serwer JS wysyła to jako "blob", może to być związane/lub problem? – ThePerson

+0

Byłoby miło mieć coś testowalnego. Mam na myśli ... Połączyłem się z usługą, ale nie mogę wysłać mi pliku, więc nie mogę sprawdzić, czy Tyrus może otrzymać wiadomość z twojego serwera. W każdym razie Tyrus pracuje również z serwerem echa, więc nie jest to naprawdę przydatny test. (po prostu wskaż klienta tyrus na "ws: //echo.websocket.org" i wyślij wiadomość). –

+0

Dzięki. Tak, działa z serwerem echa, ale echo, którego nie sądzę, odsyła bajty. Myślę, że jeśli założysz konto na storj.io (To nic nie kosztuje), możesz uruchomić "testmain" i wysłać plik, aby go przetestować. Wszystko dzieje się na Githubie, niestety jestem naprawdę zdumiony, dlaczego tak się dzieje, więc dodam nagrodę za to pytanie za 7 godzin, kiedy będę mógł. – ThePerson

Odpowiedz

2

W końcu przełączyłem się na TallNate, a ten problem nie istnieje.

Znalazłem po ustaleniu czasu, że zawsze odłączyło mnie po 30 sekundach. Zwykle odpowiedzi są szybsze niż w latach 30., więc nie jestem pewien, dlaczego zawiesił się, a następnie rozłączył. Próbowałem ustawić limit czasu w Tyrusie, ale mimo to rozłączyłem go na znaku 30s. W końcu spróbowałem TallNate, aby sprawdzić, czy mogę ustawić limit czasu ... i po wyjęciu z pudełka po prostu zadziałało.

https://github.com/TooTallNate/Java-WebSocket/wiki/Drafts

+0

Czy znalazłeś faktyczny powód? Być może drugi klient wysyła tylko okresowe pingi (które jest obsługiwane również w Tyrusie, zobacz https://tyrus.java.net/apidocs/1.13/org/glassfish/tyrus/core/TyrusSession.html#setHeartbeatInterval(long) –