1)我認爲,一旦連接是打開已經發生的請求和響應,在這一點上,以便發送標題是爲時已晚。另外,標題必須以空行結束,您省略。
2)根據演示,你甚至不用在客戶端或服務器設置頭 - 紅寶石模塊自動進行服務器端的護理頭,和HTML5自動處理的頭在客戶端。我想,這應該工作:
require "em-websocket-server"
class EchoServer < EM::WebSocket::Server
def on_connect
EM::WebSocket::Log.debug "Connected"
puts "I felt a connection."
end
def on_receive msg
puts "RECEIVED: #{msg}"
send_message msg
end
end
EM.run do
myhost = "0.0.0.0"
myport = 8000
puts "Starting WebSocket server. Listening on port #{myport}..."
EM.start_server myhost, myport, EchoServer
end
HTML文件:
<!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的工作:我得到的錯誤信息......
Firefox can't establish a connection to the server at ws://localhost:8000/.
var myWebSocket = new WebSocket("ws://localhost:8000");
我注意到,在這兩種螢火蟲和Safari的開發工具,服務器不發送二段的WebSocket-Accept報頭:
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是否支持websocket,我去了:
http://www.websocket.org/echo.html
它說我的瀏覽器支持websockets。
3)是否有任何理由必須使用em-websocket-server模塊? github上該模塊的最後修改是三年前的。只要你在ruby代碼中看到require rubygems
,那應該提醒你代碼已經老了。我嘗試了新的EM-的WebSocket模塊,我是能夠成功地傳遞數據來回使用的WebSockets兩個火狐21.0和Safari 5.1.9:
require 'em-websocket'
myhost = "0.0.0.0"
myport = 8000
EM.run {
puts "Listening on port #{myport}..."
EM::WebSocket.run(:host => myhost, :port => myport, :debug => false) do |ws|
ws.onopen do |handshake|
path = handshake.path
query_str = handshake.query
origin = handshake.origin
puts "WebSocket opened:"
puts "\t path \t\t -> #{path}"
puts "\t query_str \t -> #{query_str}"
puts "\t origin \t -> #{origin}"
end
ws.onmessage { |msg|
ws.send "Pong: #{msg}"
}
ws.onclose {
puts "WebSocket closed"
}
ws.onerror { |e|
puts "Error: #{e.message}"
}
end
}
同一個客戶端代碼。現在,響應頭包括二段的WebSocket-接受:
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-Accept標頭,並且當em-websocket-server模塊在響應中未能設置該標頭時,瀏覽器拒絕連接。
爲EM-的WebSockets服務器相關的源代碼如下所示:
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
正如你所看到的,它不設置二段的WebSocket-Accept報頭。該代碼是一種稱爲Version76模塊中,以及用於的WebSockets版本76谷歌搜索產生一個過時的協議(其中包含的請求和響應的例子):
http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
這裏是當前的WebSockets協議(它也包含請求和響應)的一個例子:
http://tools.ietf.org/html/rfc6455
結論:EM-的WebSockets服務器是過時。
優秀;謝謝!有用。一個小小的更正:EM :: WebSocket.run需要EM :: WebSocket.start。我編輯了你的答案來反映這一點。 –
@ Chad Johnson,請不要編輯我的帖子。我覺得這非常冒犯。當我發佈代碼時,它是我測試過的代碼,這是我所支持的。如果代碼不適用於您,請編寫自己的帖子,討論爲什麼它不起作用和/或發佈其他解決方案。通過編輯我的文章,你錯誤地陳述了我所說的話。我很感謝你至少通知我你編輯了我的帖子。 em :: websocket的第一個演示使用run()方法,我發現其他演示使用start()方法。我檢查了文檔,並且我不明白run()和start() – 7stud
之間的區別。如果run()不適合您,也許發佈您使用的瀏覽器和操作系統會很有幫助。我在Safari 5.1.9和Firefox 21上使用了mac osx 10.6.8,並且run()爲我工作。 – 7stud