LoginSignup
2
1

More than 5 years have passed since last update.

[Java EE] WebSocketでClientを実装

Last updated at Posted at 2018-12-21

最近、Qiita記事が進捗報告になってまいりました。
今回も、こちらの記事の続きになります。

tyrus-standalone-clientの追加

普通にクライアントプログラムを書いて実行すると、次のようなエラーが発生します。

Exception in thread "main" java.lang.RuntimeException: Could not find an implementation class.
    at javax.websocket.ContainerProvider.getWebSocketContainer(ContainerProvider.java:73)
    at Main.main(Main.java:46)

stackoverrunによると、websocketはClientのインターフェースは提供しているものの、実装を提供していないようです。
そこで、glassfishにあるtyrus-standalone-clientを導入します。
StandardWebSocketClientクラスにWebSocketContainerを実装する方法

具体的には、build.gradleのdependenciesに追加します。

dependencies {
    // 前回説明した
    compileOnly 'javax:javaee-api:8.0'
    // 今回追加するのがこれ
    compile group: 'org.glassfish.tyrus.bundles', name: 'tyrus-standalone-client', version: '1.14'
}

ClientEndPointを記述する

では、今回は早速プログラムを書いていきましょう。
<プロジェクト名> -> src -> main -> java 内(の適当なパッケージ)に、.javaファイルを作成します。


import javax.websocket.*;
import java.net.URI;
import java.util.Scanner;

// このアノテーションを付けるとクライアントのEndpointだと認識される
@ClientEndpoint
public class Client {

    public Client() {
        super();
    }

    // セッション確立時の処理
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("[セッション確立]");
    }

    // メッセージ受信時の処理
    @OnMessage
    public void onMessage(String message) {
        System.out.println("[受信]:" + message);
    }

    // メッセージ受信時の処理
    @OnError
    public void onError(Throwable th) {
        System.err.println(th.getMessage());
    }

    // セッション解放時の処理
    @OnClose
    public void onClose(Session session) {
        System.out.println("[切断]");
    }

    static public void main(String[] args) throws Exception {

        // 初期化のため WebSocket コンテナのオブジェクトを取得する
        WebSocketContainer container = ContainerProvider
                .getWebSocketContainer();
        // サーバー・エンドポイントの URI
        URI uri = URI
                .create("ws://localhost:8080/<プロジェクト名>/<リンク>");
        // サーバー・エンドポイントとのセッションを確立する
        // 実行されているクライアントから、引数に渡したクラスと同一の物を探して接続する?
        Session session = container.connectToServer(Client.class, uri);

        while (!session.isOpen()) {
            Thread.sleep(500);
        }

        System.out.println("open");

        try (Scanner s = new Scanner(System.in)) {
            String str;
            System.out.println("start loop");
            while (true) {
                str = s.nextLine();
                if(str.equals("exit")) break;
                //strの内容を送信
                session.getBasicRemote().sendText(str);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

面倒なので今回はEndpointクラス内にmainを書きましたが、分けた方がいいような気がします。

実行

まず、tomcatRunなどで、Clientの入ったサーバーを立ち上げ、その後、別窓でmainを実行します。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1