LoginSignup
2
2

More than 3 years have passed since last update.

JavaとJavaScriptでwebブラウザとのソケット通信②

Posted at

背景

過去記事:https://qiita.com/take4eng/items/d0b009c48ee8c3fe420a

上記の過去記事に記述しているように、Javaでサーバープログラムを作成しソケット通信を実施。
⇒ HTTP通信をゴリ押しで解析しているため、無駄に複雑なコードになっている。

Java EEにはsocket通信に関するAPIが多数存在し、非常に簡単に実装することが可能。
既に多くの人がまとめてくれてはいるが、実装した内容をまとめておく。

便利なAPIが用意されているのにゴリ押しで解析なんて誰もやらないよね
そりゃググってもなかなか出てこないわ…

実践内容

  1. WebSocket API の使用方法
  2. APIを使用したサーバープログラムを作成
  3. 過去記事内のクライアントプログラムコードを編集しチャットアプリ作成

WebSocket API の使用方法

基本的なWebSocket APIについて説明する。
ここで紹介するもの以外にも多数のAPIが存在するが、必要ならググると良い。

Endpointクラスの作成

import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/コンテキストパス")
public class SanpleEndpoint {
}
  1. ServerEndpointクラスをインポート
  2. クラスにアノテーション@ServerEndpointを付与
  3. ファイルの場所を示すコンテキストパスを記述

処理メソッドの作成

/*
各クラスをインポートしておく
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
*/

//クライアントと接続したときの処理
@OnOpen
public void onOpen(Session session) {
}

//クライアントからメッセージを受け取ったときの処理
@OnMessage
public void onMessage(String message) {
}

//エラーが発生したときの処理
@OnError
public void onError(Throwable error) {
}

//クライアントと接続が切れたときの処理
@OnClose
public void onClose(Session session) {
}
  1. 必要なクラスをインポート
  2. メソッドに対応した各アノテーションを付与
  3. 引数は必要に応じて変更 , 追加可能

APIを使用したサーバープログラムを作成

サーバープログラム
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

// Webソケットのサーバ側クラスであること表すアノテーション。
// 引数(wSck)はクライアントから接続時、使われるURIを表す。
@ServerEndpoint(value = "/wSck")
public class SocketFree2 {

    //クライアントのセッションスレッドを作成(クライアント毎にそれぞれのセッションを保存)
    //Set:重複要素のないコレクション
    //CopyOnWriteArrayList:java.util.Setをスレッドセーフにしたもの
    private static Set<Session> user = new CopyOnWriteArraySet<>();

    @OnOpen//クライアントと接続したとき
    public void onOpen(Session mySession) {
        System.out.println("connect ID:"+mySession.getId());//session.getId():セッションIDを取得
        user.add(mySession);//クライアント毎のセッションをリストに追加
    }

    @OnMessage//クライアントからデータが送信されたとき
    public void onMessage(String text , Session mySession) {//引数は送信されたテキストと送信元のセッション
        System.out.println(text);
        //getAsyncRemote():RemoteEndpointのインスタンスを取得
        //sendText(String):クライアントにテキストを送信
        for (Session user : user) {
            user.getAsyncRemote().sendText(text);
            System.out.println(user.getId()+"番目に"+mySession.getId()+"番目のメッセージを送りました!");
        }
        if(text.equals("bye")) onClose(mySession);//textが「bye」なら切断する
    }

    @OnClose//クライアントが切断したとき
    public void onClose(Session mySession) {
        System.out.println("disconnect ID:"+mySession.getId());
        user.remove(mySession);//切断したクライアントのセッションをリストから削除
        try {
            mySession.close();//closeメソッドで切断
        } catch (IOException e) {
            System.err.println("エラーが発生しました: " + e);
        }
    }

}

コードの解説

1.クラスにEndpointアノテーション@ServerEndpointを付与し、コンテキストパスを記述
@ServerEndpoint(value = "/wSck")

2.各クライアントを識別するリストを作成
private static Set<Session> user = new CopyOnWriteArraySet<>();

3.onOpenメソッド:クライアントのセッションをリストに追加
user.add(mySession);

4.onMessageメソッド:受信したテキストをそのままクライアントへ送信
⇒ for文で接続しているクライアント全員に送信する
user.getAsyncRemote().sendText(text);

5.onCloseメソッド:接続が切れたクライアントを削除
5-1.userリストから削除:user.remove(mySession);
5-2.セッションを削除し接続を切る:mySession.close();

実行結果

クライアントプログラムのアドレスを変更し、webブラウザで実行。
※コード内容は過去記事を参照
var wSck= new WebSocket("ws://localhost:8080/プロジェクト名/コンテキストパス");
(今回なら"ws://localhost:8080/freeWeb2/wSck")

image.png
送信した内容が表示されるチャットアプリが完成。
複数のブラウザからのアクセスにも対応している。

感想

APIを使用することで非常に簡単にソケット通信を行うことができた。
過去記事で記述しのものと比べるとコードの記述量は約1/4。すごい。超簡単。

他にもエンコード、デコード処理やjsonデータの扱いについても簡単にできるらしい。
今回は使用していないが、本格的な開発をするなら必要になるだろう。
詳細は参考ページを参照。

参考ページ

2
2
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
2