世界上最伟大的投资就是投资自己的教育

全场限时 5 折

首页WebSocket
随风 · 练气

Websocket 学习笔记系列文章教程之 客户端详解 (三)

随风发布于3268 次阅读

1. 介绍

上一篇文章websocket 之简单的服务器端 (二)介绍了两个简单的 websocket 服务器,并且介绍了如何用 javascript 连接上 websocket 服务器。除了能用浏览器的 javascript 连接上,还可以用任何编程语言,因为 websocket 协议是基于 TCP 协议请求的,只要能发送 TCP socket 请求,就可以发送 websocket 请求,这篇文章来讲述如何用 ruby 来发送 websocket 请求,并讲讲其原理。

2. websocket-ruby

websocket-ruby是一个纯 ruby 实现 websocket 请求的 gem,它支持很多版本的 websocket。比如官方列出的:

学习它,可以让我们对 websocket 协议的客户端和服务器的实现更为了解。

首先安装它。

$ gem install "websocket"

来看一个最简单的例子,客户端请求 websocket 请求。

@handshake = WebSocket::Handshake::Server.new

# Parse client request
@handshake << <<EOF
GET /demo HTTP/1.1\r
Upgrade: websocket\r
Connection: Upgrade\r
Host: example.com\r
Origin: http://example.com\r
Sec-WebSocket-Version: 13\r
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r
\r
EOF

# All data received?
@handshake.finished?

# No parsing errors?
@handshake.valid?

# Create response
puts @handshake.to_s

因为我们说过 websocket 协议是基于 tcp 协议之上,所以我们可以发送类似的 socket 请求。

@handshake变量就是我们 socket 请求的内容。我们主要来看这部分。

其中,第二行代码@handshake << <<EOF发送的内容,跟之前上一篇文章在浏览器的请求头信息是差不多的,其中来看看Sec-WebSocket-VersionSec-WebSocket-Key

Sec-WebSocket-Version表示的是 websocket 使用的版本,客户端和服务器端都会根据客户端发送的版本号,进行相应的处理,不同的版本对应不同的处理方式,这些都是 websocket-ruby 实现好的。

比如源码中是这样实现的:

# https://github.com/imanel/websocket-ruby/blob/master/lib/websocket/handshake/client.rb#L103
def include_version
  @handler = case @version
             when 75 then Handler::Client75.new(self)
             when 76, 0 then Handler::Client76.new(self)
             when 1..3  then Handler::Client01.new(self)
             when 4..10 then Handler::Client04.new(self)
             when 11..17 then Handler::Client11.new(self)
             else fail WebSocket::Error::Handshake::UnknownVersion
             end
end

Sec-WebSocket-Key 是用 base64 算法加密过的随机串,每次请求都不一样,上面是自己指定的,但是它可以由客户端计算出来,比如

# https://github.com/imanel/websocket-ruby/blob/master/lib/websocket/handshake/handler/client04.rb#L33
def key
  @key ||= Base64.encode64((1..16).map { rand(255).chr } * '').strip
end

现在回头来看看上面的演示代码到底输出了什么样的结果。

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

返回的状态码是 101,并且返回了 Sec-WebSocket-Accept 的内容。

Sec-WebSocket-Accept 的计算方式是这样的,把客户端发送过来的 “Sec-WebSocket-Key” 加上一个魔幻字符串 “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”。使用 SHA-1 加密,之后进行 BASE-64 编码,将结果做为 “Sec-WebSocket-Accept” 头的值,返回给客户端。

它的算法是这样的:

# https://github.com/imanel/websocket-ruby/blob/master/lib/websocket/handshake/handler/server04.rb#L31
def signature
  return unless key
  string_to_sign = "#{key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
  Base64.encode64(Digest::SHA1.digest(string_to_sign)).chomp
end

3. websocket-client-simple

websocket-client-simple是对 websocket-ruby 这个 gem 的进一步封装,它的源码只有一个文件。还记得上一篇文章,用 javascript 写 websocket 请求的例子吗,ruby 也可以有类似的语法,就是用这个 gem。

require 'websocket-client-simple'

ws = WebSocket::Client::Simple.connect 'ws://localhost:8080/echo'

ws.on :message do |msg|
  puts "received data: " + msg.data
end

ws.on :open do
  ws.send 'hello!!!'
end

ws.on :close do |e|
  p e
  exit 1
end

ws.on :error do |e|
  p e
end

loop do
  ws.send STDIN.gets.strip
end

这个例子演示了,输入什么,websocket 就会返回相同的输入。

本篇完结。

下一篇: websocket 之实现简易聊天室 (四)

本站文章均为原创内容,如需转载请注明出处,谢谢。

0 条回复
暂无回复~~
相关小书
websocket教程

websocket教程

从websocket的介绍开始,从入门到精通

发表于

喜欢
统计信息
    学员: 29066
    视频数量: 1973
    文章数量: 489

© 汕尾市求知科技有限公司 | Rails365 Gitlab | Qiuzhi99 Gitlab | 知乎 | b 站 | 搜索

粤公网安备 44152102000088号粤公网安备 44152102000088号 | 粤ICP备19038915号

Top