RubyでつくるWebSocketサーバーにprotocol-websocket gemを取り入れる その2 - @ledsun blog でリクエスト文字列の解析をWEBrickに置き換えました。
今度はレスポンス文字列の作成にWEBrick::HTTPResponse
を使います。
require 'socket' require 'webrick' require 'protocol/websocket/headers' def read_headers_from(socket) request = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP) request.parse(socket) request.header end def calculate_accept_nonce_from(headers) key = headers[::Protocol::WebSocket::Headers::SEC_WEBSOCKET_KEY].first ::Protocol::WebSocket::Headers::Nounce.accept_digest(key) end server = TCPServer.new 'localhost', 2345 loop do # ここら辺はecho_server.rbと同じ。純粋なTCP通信 socket = server.accept # HTTPリクエストheaderを読み込む headears = read_headers_from socket # WebSocketリクエストかどうかを判定する unless headears["upgrade"] = ::Protocol::WebSocket::Headers::PROTOCOL puts "Not a websocket request" socket.close next end response_key = calculate_accept_nonce_from headears puts "response_key: #{response_key}" response = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP) response.status = 101 response.upgrade! ::Protocol::WebSocket::Headers::PROTOCOL response['Sec-WebSocket-Accept'] = response_key # ソケットそのものはHTTP通信で使われているものと同じ response.send_response socket puts 'Handshake response sent' # ここからはWebSocket通信 first_byte = socket.getbyte fin = first_byte & 0b10000000 opcode = first_byte & 0b00001111 raise 'fin bit is not set' unless fin raise 'opcode is not a text' unless opcode == 0x1 second_byte = socket.getbyte is_masked = second_byte & 0b10000000 payload_size = second_byte & 0b01111111 raise 'mask bit is not set' unless is_masked raise 'payload size > 125 is not supported' unless payload_size <= 125 puts "Payload size: #{payload_size}" mask = 4.times.map { socket.getbyte } puts "Mask: #{mask}" data = payload_size.times.map.with_index { socket.getbyte ^ mask[_2 % 4] } puts "Data: #{data.pack('C*')}" # クライアントにデータを返す response_message = "Loud and clear!" response = [0b10000001, response_message.size, response_message ].pack("CCA#{response_message.size}") socket.write response socket.close end
今の時点ではWEBrick::HTTPResponse
とProtocol::HTTP::Response
の違いを理解できていません。