首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与Ruby的WebSocket握手::WebSocket::Server

与Ruby的WebSocket握手::WebSocket::Server
EN

Stack Overflow用户
提问于 2013-06-28 22:14:34
回答 1查看 4.3K关注 0票数 2

我正在尝试在JavaScript中与Rails应用程序创建一个简单的JavaScript连接。我得到以下信息:

连接到'ws://localhost:4000/‘的WebSocket连接失败: WebSocket握手时出错:'Sec-WebSocket-Accept’标头丢失

我做错了什么?这是我的代码:

JavaScript:

代码语言:javascript
复制
var socket = new WebSocket('ws://localhost:4000');

socket.onopen = function() {
  var handshake =
    "GET / HTTP/1.1\n" +
    "Host: localhost\n" +
    "Upgrade: websocket\n" +
    "Connection: Upgrade\n" +
    "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\n" +
    "Sec-WebSocket-Protocol: quote\n" +
    "Sec-WebSocket-Version: 13\n" +
    "Origin: http://localhost\n";

  socket.send(handshake);
};

socket.onmessage = function(data) {
  console.log(data);
};

红宝石:

代码语言:javascript
复制
require 'rubygems'
require 'em-websocket-server'

module QuoteService
  class WebSocket < EventMachine::WebSocket::Server
    def on_connect
      handshake_response =  "HTTP/1.1 101 Switching Protocols\n"
      handshake_response << "Upgrade: websocket\n"
      handshake_response << "Connection: Upgrade\n"
      handshake_response << "Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=\n"
      handshake_response << "Sec-WebSocket-Protocol: quote\n"

      send_message(handshake_response)
    end

    def on_receive(data)
      puts 'RECEIVED: ' + data
    end
  end
end

EventMachine.run do
  print 'Starting WebSocket server...'
  EventMachine.start_server '0.0.0.0', 4000, QuoteService::WebSocket
  puts 'running'
end

握手头为每个维基百科

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-29 07:51:52

  1. 我认为,一旦连接打开,请求和响应已经发生,因此在此时发送标头为时已晚。此外,标头必须以空行结尾,这是您省略的。
  2. 根据演示,您甚至不必在客户机或服务器中设置标头-- ruby模块会自动处理服务器端的头,而html5会自动处理客户端的标头。我认为这应该是可行的: 需要"em-websocket-server“ 类EchoServer < EM::WebSocket::Server on_connect EM::WebSocket::Log.debug "Connected“的意思是”我感觉到了一种联系“。结束 def on_receive msg将“接收:#{ msg }”send_message msg端 结束 EM.run do myhost = "0.0.0.0“myport = 8000 puts”启动WebSocket服务器。侦听端口#{myport}.“EM.start_server myhost,myport,EchoServer end

html文件:

代码语言:javascript
复制
<!DOCTYPE html> <html> <head><title>Test</title>

<script type="text/javascript">

  var myWebSocket = new WebSocket("ws://localhost:8000");

  myWebSocket.onopen = function(evt)    { 
    console.log("Connection open. Sending message..."); 
    myWebSocket.send("Hello WebSockets!");       };

  myWebSocket.onmessage = function(evt)    { 
    console.log(evt.data);
    myWebSocket.close();   };

  myWebSocket.onclose = function(evt)    { 
    console.log("Connection closed.");    };

  myWebSocket.onerror = function(err)   {
    alert(err.name + " => " + err.message);   } </script>

</head> <body>   <div>Hello</div> </body> </html>

而且它在Safari 5.1.9 (这是一个较旧的浏览器)中也能工作:我看到了服务器和客户端的预期输出。但是,这些代码在Firefox 21中不起作用:我得到了错误消息.

代码语言:javascript
复制
Firefox can't establish a connection to the server at ws://localhost:8000/.
    var myWebSocket = new WebSocket("ws://localhost:8000");

我注意到,在Firebug和Safari Developer工具中,服务器都不发送Sec-WebSocket-Accept:

代码语言:javascript
复制
Response Headers

Connection          Upgrade
Upgrade         WebSocket
WebSocket-Location  ws://localhost:8000/
WebSocket-Origin    null


Request Headers

Accept                  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding         gzip, deflate
Accept-Language         en-US,en;q=0.5
Cache-Control           no-cache
Connection          keep-alive, Upgrade
DNT                 1
Host                    localhost:8000
Origin                  null
Pragma                  no-cache
Sec-WebSocket-Key   r9xT+ywe533EHF09wxelkg==
Sec-WebSocket-Version   13
Upgrade                 websocket
User-Agent          Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:21.0) Gecko/20100101 Firefox/21.0

在Firefox 21.0中,我所做的任何尝试都无法使代码工作。为了检查Firefox 21.0是否甚至支持websockets,我转到:

代码语言:javascript
复制
http://www.websocket.org/echo.html  

上面说我的浏览器支持websockets。

  1. 你有什么理由要使用em-websocket服务器模块吗?上一次修改github上的模块是三年前。每当您在ruby代码中看到require rubygems时,这应该会提醒您代码是旧的。我尝试了较新的em-websocket模块,并且能够在Firefox 21.0和Safari 5.1.9上使用websocket成功地来回传输数据: 需要“他们-websocket” myhost = "0.0.0.0“myport = 8000 EM.run {放置“侦听端口#{myport}.” EM::WebSocket.run(:主机=> myhost,:端口=> myport,:debug => false) ws.onopen做握手,握手,query_str = handshake.query query_str = handshake.origin打开:放置“t路径\t -> #{ path }”放置"\t query_str \t -> #{query_str}“放置"\t原产地\t -> #{原产地}”结束ws.onmessage {\t->##{原产地"Pong:#{msg}“} ws.onclose { puts”WebSocket已关闭的“}{{e.message}”}} 端}

客户端代码相同。现在响应头包括Sec-WebSocket-Accept:

代码语言:javascript
复制
Response Headers

Connection          Upgrade
Sec-WebSocket-Accept    LyIm6d+kAAqkcTR744tVK9HMepY=
Upgrade                 websocket


Request Headers

Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Cache-Control   no-cache
Connection  keep-alive, Upgrade
DNT 1
Host    localhost:8000
Origin  null
Pragma  no-cache
Sec-WebSocket-Key   pbK8lFHQAF+arl9tFvHn/Q==
Sec-WebSocket-Version   13
Upgrade websocket
User-Agent  Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:21.0) Gecko/20100101 Firefox/21.0

在您的代码中,我认为您没有设置任何标题。相反,您只是来回发送消息,这些消息恰好包含看起来像头的字符。显然,您的浏览器需要Sec-websocket-接受响应中的报头,然后才允许连接,当em-websocket-服务器模块无法在响应中设置该标头时,浏览器拒绝连接。

em-websockets的相关源代码如下所示:

代码语言:javascript
复制
module EM
  module WebSocket
    module Protocol
      module Version76
      
        # generate protocol 76 compatible response headers
        def response
          response = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
          response << "Upgrade: WebSocket\r\n"
          response << "Connection: Upgrade\r\n"
          response << "Sec-WebSocket-Origin: #{origin}\r\n"
          response << "Sec-WebSocket-Location: #{scheme}://#{host}#{path}\r\n"
  
          if protocol
            response << "Sec-WebSocket-Protocol: #{protocol}\r\n"
          end

          response << "\r\n"
          response << Digest::MD5.digest(keyset)

          response
        end

如您所见,它没有设置Sec-WebSocket-Accept。该代码位于一个名为Version76的模块中,搜索76将产生一个过时的协议(其中包含一个请求和响应的示例):

https://datatracker.ietf.org/doc/html/draft-hixie-thewebsocketprotocol-76

下面是当前的websockets协议(其中还包含一个请求和响应的示例):

https://www.rfc-editor.org/rfc/rfc6455

结论:em-websockets是过时的.

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17374453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档