WebSocket概要
WebSocketは、javascriptを通してサーバと接続を行い継続的に通信(ソケット通信)を行えようにするための仕組みである。
WebSocketのメソッド
- send() : データ送信
- close() : 通信切断
WebSocketのリスナー
- onopen : 接続確立時
- onerror : エラー時
- onclose : 切断時
- onmessage : データ受信時
WebSocketのステータス
- CONNECTING(0)
- OPEN(1)
- CLOSING(2)
- CLOSED(3)
・サンプルコード
クライアント側
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title> WebSocketサンプル </title> </head> <body> <script type="text/javascript"> // WebSocket生成 var webSocket = new WebSocket("ws://127.0.0.1:30000"); // 接続リスナー webSocket.onopen = function() { alert("サーバ接続成功"); // 发送消息 webSocket.send("クライアントからの送信データ"); } // データ受信リスナー webSocket.onmessage = function(event) { alert("受信データ:" + event.data); } </script> </body> </html>
サーバ側
import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.security.MessageDigest; import java.util.Base64; import java.util.Base64.Encoder; import java.util.regex.Matcher; import java.util.regex.Pattern; public class SimpleServer { public SimpleServer() throws Exception { // サーバソケット ServerSocket ss = new ServerSocket(30000); // 受け入れ待ち Socket socket = ss.accept(); // 入力ストリーム InputStream in = socket.getInputStream(); // 出力ストリーム OutputStream out = socket.getOutputStream(); // バッファサイズ byte[] buff = new byte[1024]; int count = -1; String req = ""; // ここでクライアントに接続を確立 count = in.read(buff); // データ取得 req = new String(buff, 0, count); System.out.println("リクエスト" + req); // WebSocketのキー取得 String secKey = getSecWebSocketKey(req); System.out.println("secKey = " + secKey); // ヘッダー String response = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: " + "websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " + getSecWebSocketAccept(secKey) + "\r\n\r\n"; System.out.println("secAccept = " + getSecWebSocketAccept(secKey)); out.write(response.getBytes()); // 再度データ読み取り count = in.read(buff); System.out.println("受信データバイト数" + count); /* * WebSocketプロトコール 3~6は隠しコード 7バイト目からがデータ 3~6で後ろのデータを処理 */ for (int i = 0; i < count - 6; i++) { buff[i + 6] = (byte) (buff[i % 4 + 2] ^ buff[i + 6]); } System.out.println("受信データ" + new String(buff, 6, count - 6, "UTF-8")); // 送信する際に、2バイトは必ず受信と同じである必要がある byte[] pushHead = new byte[2]; pushHead[0] = buff[0]; String pushMsg = "Welcom to WebSocket"; // 第2バイトは長さを記録 pushHead[1] = (byte) pushMsg.getBytes("UTF-8").length; // 2バイト送信 out.write(pushHead); // 有効データ送信 out.write(pushMsg.getBytes("UTF-8")); // socket終了 socket.close(); // serverクローズ ss.close(); } /** * WebSocketのキー取得 * * @param req * @return */ private String getSecWebSocketKey(String req) { Pattern p = Pattern.compile("^(Sec-WebSocket-Key:).+", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); Matcher m = p.matcher(req); if (m.find()) { // Sec-WebSocket-Key取得 String foundstring = m.group(); return foundstring.split(":")[1].trim(); } else { return null; } } /** * WebSocketのSecKeyからSecAccept計算 * * @param key * @return * @throws Exception */ private String getSecWebSocketAccept(String key) throws Exception { String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; key += guid; MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(key.getBytes("UTF-8"), 0, key.length()); byte[] sha1Hash = md.digest(); Encoder encoder = Base64.getEncoder(); return new String(encoder.encode(sha1Hash), "UTF-8"); } public static void main(String[] args) throws Exception { new SimpleServer(); } }
サーバ起動後に、htmlを開く。