exemplo simples do cliente javax.websocket

104

Alguém pode me fornecer um exemplo muito simples de cliente de websocket usando javax.websocket?

Quero me conectar ao websocket (ws: //socket.example.com: 1234), enviar mensagem (adicionar canal) e ouvir as mensagens. Todas as mensagens (enviadas e ouvidas) estão no formato JSON.

E btw esta biblioteca é a melhor para comunicação simples de websocket?

Martin
fonte

Respostas:

120

Encontrei um ótimo exemplo usando javax.websocketaqui:

http://www.programmingforliving.com/2013/08/jsr-356-java-api-for-websocket-client-api.html

Aqui está o código baseado no exemplo com link acima:

TestApp.java:

package testapp;

import java.net.URI;
import java.net.URISyntaxException;

public class TestApp {

    public static void main(String[] args) {
        try {
            // open websocket
            final WebsocketClientEndpoint clientEndPoint = new WebsocketClientEndpoint(new URI("wss://real.okcoin.cn:10440/websocket/okcoinapi"));

            // add listener
            clientEndPoint.addMessageHandler(new WebsocketClientEndpoint.MessageHandler() {
                public void handleMessage(String message) {
                    System.out.println(message);
                }
            });

            // send message to websocket
            clientEndPoint.sendMessage("{'event':'addChannel','channel':'ok_btccny_ticker'}");

            // wait 5 seconds for messages from websocket
            Thread.sleep(5000);

        } catch (InterruptedException ex) {
            System.err.println("InterruptedException exception: " + ex.getMessage());
        } catch (URISyntaxException ex) {
            System.err.println("URISyntaxException exception: " + ex.getMessage());
        }
    }
}

WebsocketClientEndpoint.java:

package testapp;

import java.net.URI;
import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;

/**
 * ChatServer Client
 *
 * @author Jiji_Sasidharan
 */
@ClientEndpoint
public class WebsocketClientEndpoint {

    Session userSession = null;
    private MessageHandler messageHandler;

    public WebsocketClientEndpoint(URI endpointURI) {
        try {
            WebSocketContainer container = ContainerProvider.getWebSocketContainer();
            container.connectToServer(this, endpointURI);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Callback hook for Connection open events.
     *
     * @param userSession the userSession which is opened.
     */
    @OnOpen
    public void onOpen(Session userSession) {
        System.out.println("opening websocket");
        this.userSession = userSession;
    }

    /**
     * Callback hook for Connection close events.
     *
     * @param userSession the userSession which is getting closed.
     * @param reason the reason for connection close
     */
    @OnClose
    public void onClose(Session userSession, CloseReason reason) {
        System.out.println("closing websocket");
        this.userSession = null;
    }

    /**
     * Callback hook for Message Events. This method will be invoked when a client send a message.
     *
     * @param message The text message
     */
    @OnMessage
    public void onMessage(String message) {
        if (this.messageHandler != null) {
            this.messageHandler.handleMessage(message);
        }
    }

    /**
     * register message handler
     *
     * @param msgHandler
     */
    public void addMessageHandler(MessageHandler msgHandler) {
        this.messageHandler = msgHandler;
    }

    /**
     * Send a message.
     *
     * @param message
     */
    public void sendMessage(String message) {
        this.userSession.getAsyncRemote().sendText(message);
    }

    /**
     * Message handler.
     *
     * @author Jiji_Sasidharan
     */
    public static interface MessageHandler {

        public void handleMessage(String message);
    }
}
Martin
fonte
1
Oi, como fazer esse código funcionar se o websocketServer está enviando um fluxo contínuo de mensagens e websocketClient precisa consumir as mensagens uma por uma? Recebo o erro "A mensagem de texto decodificada era muito grande para o buffer de saída e o endpoint não suporta mensagens parciais" depois de executar o código por cerca de um minuto
postcommenter
Certifique-se de maven-import org.java-websocket.
Albert Hendriks
9
Este código falha com o erro: Não foi possível encontrar uma classe de implementação.
Kirk Sefchik
2
@deathgaze javax.websocket api é apenas a especificação não tem implementação completa, você pode precisar pegar o arquivo jar tyrus-standalone-client-1.9.jar e tentar o mesmo exemplo que deve resolver seu problema. eu testei com meu exemplo e está funcionando bem. espero que isso ajude você.
SRK
@Martin Como posso enviar uma mensagem no Open. Exemplo: eu preciso enviar '{"type": "subscribe", "symbol": "AAPL"}' ao abrir o websocket para assinar.
Buddhika
40

TooTallNate tem um cliente simples https://github.com/TooTallNate/Java-WebSocket

Basta adicionar o java_websocket.jar na pasta dist em seu projeto.

 import org.java_websocket.client.WebSocketClient;
 import org.java_websocket.drafts.Draft_10;
 import org.java_websocket.handshake.ServerHandshake;
 import org.json.JSONException;
 import org.json.JSONObject;

  WebSocketClient mWs = new WebSocketClient( new URI( "ws://socket.example.com:1234" ), new Draft_10() )
{
                    @Override
                    public void onMessage( String message ) {
                     JSONObject obj = new JSONObject(message);
                     String channel = obj.getString("channel");
                    }

                    @Override
                    public void onOpen( ServerHandshake handshake ) {
                        System.out.println( "opened connection" );
                    }

                    @Override
                    public void onClose( int code, String reason, boolean remote ) {
                        System.out.println( "closed connection" );
                    }

                    @Override
                    public void onError( Exception ex ) {
                        ex.printStackTrace();
                    }

                };
 //open websocket
 mWs.connect();
 JSONObject obj = new JSONObject();
 obj.put("event", "addChannel");
 obj.put("channel", "ok_btccny_ticker");
 String message = obj.toString();
 //send message
 mWs.send(message);

// e para fechar websocket

 mWs.close();
TCassells
fonte
4
Trabalhei em Windows 7, windows 8 e OS X mountain lion usando eclipse, servidor Ubuntu.
TCassells de
1
por que você escolheria esta biblioteca em vez das javax?
BvuRVKyUVlViVIc7
2
porque é obviamente mais simples
Kyle Luke
4
quais alterações são necessárias para oferecer suporte ao protocolo wss (ws protegido)?
Mihailo Stupar
2
Ótima biblioteca, mas tem problemas com wss. O projeto tem vários problemas em aberto, e o desenvolvedor comenta que não tem mais tempo.
SiKing
18

Dê uma olhada nestes exemplos de Java EE 7 de Arun Gupta.

Eu fiz o garfo no github .

a Principal

/**
 * @author Arun Gupta
 */
public class Client {

    final static CountDownLatch messageLatch = new CountDownLatch(1);

    public static void main(String[] args) {
        try {
            WebSocketContainer container = ContainerProvider.getWebSocketContainer();
            String uri = "ws://echo.websocket.org:80/";
            System.out.println("Connecting to " + uri);
            container.connectToServer(MyClientEndpoint.class, URI.create(uri));
            messageLatch.await(100, TimeUnit.SECONDS);
        } catch (DeploymentException | InterruptedException | IOException ex) {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

ClientEndpoint

/**
 * @author Arun Gupta
 */
@ClientEndpoint
public class MyClientEndpoint {
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("Connected to endpoint: " + session.getBasicRemote());
        try {
            String name = "Duke";
            System.out.println("Sending message to endpoint: " + name);
            session.getBasicRemote().sendText(name);
        } catch (IOException ex) {
            Logger.getLogger(MyClientEndpoint.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @OnMessage
    public void processMessage(String message) {
        System.out.println("Received message in client: " + message);
        Client.messageLatch.countDown();
    }

    @OnError
    public void processError(Throwable t) {
        t.printStackTrace();
    }
}
Koekiebox
fonte
Você deve mencionar que ele requer a dependência de websocket enviada separadamente
Java Main
1

Use esta biblioteca org.java_websocket

A primeira coisa que você deve importar essa biblioteca em build.gradle

repositories {
 mavenCentral()
 }

em seguida, adicione a implementação na dependência {}

implementation "org.java-websocket:Java-WebSocket:1.3.0"

Então você pode usar este código

Em sua atividade declare objeto para Websocketclient como

private WebSocketClient mWebSocketClient;

em seguida, adicione este método para retorno de chamada

 private void ConnectToWebSocket() {
URI uri;
try {
    uri = new URI("ws://your web socket url");
} catch (URISyntaxException e) {
    e.printStackTrace();
    return;
}

mWebSocketClient = new WebSocketClient(uri) {
    @Override
    public void onOpen(ServerHandshake serverHandshake) {
        Log.i("Websocket", "Opened");
        mWebSocketClient.send("Hello from " + Build.MANUFACTURER + " " + Build.MODEL);
    }

    @Override
    public void onMessage(String s) {
        final String message = s;
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                TextView textView = (TextView)findViewById(R.id.edittext_chatbox);
                textView.setText(textView.getText() + "\n" + message);
            }
        });
    }

    @Override
    public void onClose(int i, String s, boolean b) {
        Log.i("Websocket", "Closed " + s);
    }

    @Override
    public void onError(Exception e) {
        Log.i("Websocket", "Error " + e.getMessage());
    }
};
mWebSocketClient.connect();

}

Muhammed Fasil
fonte
-2

Eu tenho Spring 4.2 em meu projeto e muitas implementações SockJS Stomp geralmente funcionam bem com implementações Spring Boot. Esta implementação do Baeldung funcionou (para mim, sem mudar do Spring 4.2 para 5). Depois de usar as dependências mencionadas em seu blog, ele ainda me deu ClassNotFoundError. Eu adicionei a dependência abaixo para corrigi-lo.

<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.2.3.RELEASE</version>
    </dependency>
veritas
fonte