WebSocketとは

WebSocketは、クライアント(例えばウェブブラウザ)とサーバー間で双方向の通信を可能にするプロトコルです。
HTTPを使用して接続を確立した後、WebSocketプロトコルに切り替えることで、双方がメッセージをリアルタイムでやり取りできるようになります。
これにより、チャットアプリケーションやリアルタイム更新が必要なウェブアプリケーションに適しています。

特徴

双方向通信:
クライアントとサーバーが相互にデータを送受信できます。
低遅延:
通常のHTTPリクエストと比較して、低遅延での通信が可能です。
軽量なヘッダー:
WebSocketフレームは、HTTPヘッダーに比べてはるかに軽量です。
持続的な接続:
接続が確立された後、継続的にデータを交換できます。

使用例

チャットアプリ:
ユーザーがリアルタイムでメッセージを送受信できる。
リアルタイム通知:
新しい通知を即座にユーザーに届ける。
ライブフィード:
株価やスポーツのスコアなどのリアルタイムデータ更新。
オンラインゲーム:
プレイヤー間のリアルタイム通信。

WebSocketを使うことで、リアルタイムでのデータ通信が簡単に実現でき、よりインタラクティブなウェブアプリケーションの構築が可能になります。

WebSocketサーバーとクライアント側の処理の実装例

ここでは、クライアント側はJavaScript、サーバー側はJavaで実装する例を記載します。

Java側(サーバー側)の実装例

Spring Bootを使用してWebSocketサーバーを実装する場合、SpringのWebSocketサポートを活用して簡単に実現できます。
以下に、Spring BootでWebSocketサーバーを実装する具体的な例を示します。

依存関係の追加

まずは、pom.xmlに必要な依存関係を追加します。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
WebSocketハンドラの実装

次に、WebSocketハンドラを実装します。
Springでは、WebSocketHandlerインタフェースを実装することでカスタムのWebSocketハンドラを定義できます。

import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

@Component
public class WebSocketHandler extends TextWebSocketHandler {

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("WebSocket connection established: " + session.getId());
        session.sendMessage(new TextMessage("Hello Client!"));
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("Message received: " + message.getPayload());
        session.sendMessage(new TextMessage("Echo: " + message.getPayload()));
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("WebSocket connection closed: " + session.getId());
    }
}
WebSocketコンフィギュレーション

次に、WebSocketを有効にするためのコンフィギュレーションクラスを作成します。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new WebSocketHandler(), "/websocket")
                .setAllowedOrigins("*");
    }
}
Spring Bootアプリケーションのエントリーポイント

最後に、Spring Bootアプリケーションを起動するエントリーポイントを作成します。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebSocketServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebSocketServerApplication.class, args);
    }
}

これで、Spring Bootを使用してWebSocketサーバーを実装する準備が整いました。
WebSocketハンドラは/websocketエンドポイントでリクエストを処理し、クライアントからのメッセージを受信してエコーバックします。

クライアント側の実装(JavaScript)

WebSocketクライアントをJavaScriptで実装する例を示します。

const socket = new WebSocket('ws://localhost:8080/websocket');

socket.addEventListener('open', function (event) {
    socket.send('Hello Server!');
});

socket.addEventListener('message', function (event) {
    console.log('Message from server:', event.data);
});

socket.addEventListener('close', function (event) {
    console.log('WebSocket connection closed');
});

socket.addEventListener('error', function (event) {
    console.error('WebSocket error:', event);
});

これで、Javaを使用した基本的なWebSocketサーバーのセットアップが完了です。
クライアントからのメッセージを受信し、それをエコーするサーバーが動作するようになります。

ApacheやNginxの設定変更でWebSocketを有効化

WebSocketを有効化する場合、ApacheやNginxの設定を変更する必要があります。
WebSocketはHTTPとは異なるプロトコルであり、通常のHTTPリクエストとは異なる形式で通信を行います。
そのため、WebSocketの接続を正しく処理するためには、Webサーバーの設定を調整する必要があります。

具体的には、以下のような設定が必要です。

Apache HTTP Serverの設定(例)

Apache HTTP Serverの場合、mod_proxyモジュールを使用してWebSocketをプロキシすることが一般的です。
以下は、ApacheでWebSocketをプロキシする設定例です。

1. httpd.confまたは対象のバーチャルホストの設定ファイルに以下を追加します。

<VirtualHost *:80>
    ServerName example.com

    ProxyPass /websocket ws://localhost:8080/websocket
    ProxyPassReverse /websocket ws://localhost:8080/websocket

    # その他の設定...

</VirtualHost>

この設定では、/websocketへのリクエストをWebSocketのエンドポイント(ここではws://localhost:8080/websocket)にプロキシします。

2. mod_proxy_wstunnelモジュールが必要な場合は、次のようにロードします。

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

Nginxの設定(例)

Nginxの場合も、proxy_passディレクティブを使用してWebSocketをプロキシします。

server {
    listen 80;
    server_name example.com;

    location /websocket {
        proxy_pass http://localhost:8080/websocket;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        # その他の設定...
    }

    # その他の設定...
}

この設定では、/websocketへのリクエストをWebSocketのエンドポイント(ここではhttp://localhost:8080/websocket)にプロキシし、UpgradeおよびConnectionヘッダーを適切に設定してWebSocketの接続を可能にします。

まとめ

WebSocketを使用する場合は、ApacheやNginxの設定を適切に調整してWebSocketのプロキシ設定を追加する必要があります。
これにより、Webサーバーを通じてWebSocket接続を正しく処理し、バックエンドのWebSocketサーバーとクライアント間の通信を可能にします。