65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Sec-Websocket-Protocol

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2014 年 2 月 2 日

CPOL

6分钟阅读

viewsIcon

56537

downloadIcon

692

一个使用 Websocket(php/js)上的不同协议的示例服务器和客户端

引言

本文介绍了一个示例 websocket 服务器(碰巧是用 PHP 编写的)、Sec-WebSocket-Protocol 标头的用法以及 HTML/JavaScript 中的示例客户端。

实现协议允许单个 websocket 服务器向不同的客户端呈现不同的接口。

背景  

Websockets 在浏览器和服务器之间提供了一种连接,允许数据随时双向发送。目前有多种“服务器推送”方法,但 Websockets 有望取代大多数(如果不是全部)这些“变通方法”。  

大多数流行的桌面和移动浏览器都对Websockets 标准(根据RFC 6455)具有原生支持,并提供兼容的 JavaScript API——甚至 Internet Explorer(从 IE v11 开始)也支持。

基本的协议在 RFC 6455 中有所描述;一个二进制头包含一个操作码、长度掩码信息,后面跟着一个数据块。该规范并未定义数据如何被解释,也未定义用于启动握手的可选 HTTP 标头的值:Sec-WebSocket-Protocol

许多简单的 websocket 示例只是忽略协议,而是使用连接将字符串(可能是 JSON 编码的)发送给被设计用来理解它的某个服务器。但是,如果您将这样的客户端连接到另一个 websocket 服务器,则可能会发生任何事情。

因此,您可以定义自己的解释 websocket 数据的方法,称之为协议,给您的协议命名为“myprotocol”,然后让您的 JavaScript 像这样打开一个 websocket 连接:

var host = "ws://some.host.or.other/
var protcol="myprotocol";
socket = new WebSocket(host, protocol);

然后,服务器就知道它必须就此连接与“myprotocol”进行通信。

实际上,服务器可以根据协议和/或 URL 的内容来编写以处理不同的数据,因为这一切都取决于开发人员。

我们这里看的是一个可以处理多种不同协议的单个 websocket 服务器的示例——允许不同的客户端从同一个服务器请求不同格式的数据。 

“真实”与“欺骗”的 websocket 服务器

我不确定是否真的有这样的定义,但是…… 

一个“真实”的 websocket 服务器将与一个标准的 Web 服务器集成,该服务器接受“http://some.url/”之类的请求并提供 HTTP 服务,并接受“ws://something”之类的请求并提供 websocket 服务——所有这些通常都在端口 80 上。

一个“欺骗”的 websocket 服务器只是运行并在指定的端口号上接受套接字连接。下面的示例 PHP 服务器是“欺骗”的,因为它可以在命令行或标准 Web 服务器(端口 80)上执行,然后它自己在不同的端口上接受 websocket 连接。

这里的示例是一个用于开发用途的“欺骗”websocket 服务器。您可能不想在生产环境中使用它微笑 | :)

如果您想与此一起使用一个简单的 Web 服务器,您可以尝试CivetwebMongoose

代码做什么?

websocket2.php

websocket2.php 是一个用 PHP 编写的示例 websocket 服务器,如果您安装了 PHP,可以在命令行上运行它,或者从本地 Web 服务器运行它。只要您配置好路由器等允许其监听的端口号,它就可以接受来自网络任何地方的连接。

它是为了只接受具有有效协议的连接而编写的。如果浏览器中的 JavaScript 请求的是:

socket = new WebSocket(host, 'myprotocol'); 

那么,使用 Chrome 的开发者工具(网络/标头)查看连接时的标头,我们会看到: 

Request URL:ws://192.168.0.42:12352/websocket/websocket2.php
Request Method:GET
Status Code:101 Switching Protocols
 
Request Headers
Cache-Control:no-cache
Connection:Upgrade
Host:tonywilk.no-ip.org:12352
Origin:http://192.168.0.42
Pragma:no-cache
Sec-WebSocket-Key:DMF3ByMTLq+cp7AyMN0qUA==
Sec-WebSocket-Protocol:myprotocol           <-- browser sends 'can I have this protocol'
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent: ... Chrome/32.0.1700.102 Safari/537.36
 
Response Headers
Connection:Upgrade
Sec-WebSocket-Accept:L6wqtsHk6dzD+kd9NCYT6Wt7OCU=
Sec-WebSocket-Protocol:myprotocol           <-- server replies ok
Upgrade:WebSocket

事实上,客户端可以这样请求多个协议:

Sec-WebSocket-Protocol:myprotocolv1,myprotocolv2,anotherprotcol

允许服务器决定提供哪个协议。

我们的示例服务器代码有一个处理程序列表,每个协议类型都有一个:

$protocolHandlers= array(
   "echo"    => 'doEcho',     // simply echos payload to ALL clients
   "chat"    => 'doChat',     // sends "[name] message..." to all other 'chat' clients
   "command" => 'doCommand',  // accepts commands to the server
);
include('./JSONsvc2.php');    // JSONsvc: adds protocol handler "JSONsvc"

(包含的 JSONsvc2.php 会动态地将“JSONsvc”添加到此列表中。)

这些示例协议非常简单,但请注意它们之间的区别——这有望证明不同协议在服务器端的有用性——即使只是为了分离代码和开发同一核心服务器的备用接口,并且能够轻松地与所有客户端进行通信。

JSONsvc 协议稍微复杂一些,将在以后的文章中介绍。
(同时,源代码中有很多注释。)  

websocket2.html

一个示例客户端,它使用其任何协议连接到服务器。它有一个帮助按钮微笑 | :)

如果将其与 PHP 文件一起放在 Web 服务器上,可以通过加载到不可见的 iframe 中来启动 PHP 服务器,或者您可以在其他某个套接字上运行 PHP 服务器,然后仅填写相关的 IP 地址/端口号信息。PHP 服务器会尝试通过每 20 秒发送一个 websocket ping 来保持套接字打开,JavaScript API 会很乐意地回复。

websocket 服务器的默认端口号是 12352。这可以在命令行或 URL 中更改(有关详细信息,请参阅源代码)。

使用代码 

将 .zip 文件解压到某个名为“wsdemo”的目录。

如果此目录位于具有 PHP 的本地 Web 服务器上,那么您就可以开始了,只需浏览到 http://myserver/wsdemo/websockets2.html——假设您对 myserver 的访问允许访问端口 12352。 

从浏览器,如果您希望页面为您启动 PHP 脚本,您必须设置 PHP 脚本的位置,方法是输入:  

php script url: http://myserver/wsdemo/websockets2.php 

以在不同的端口上运行: 

php script url: http://myserver/wsdemo/websockets2.php?port=9999

或者,您可以通过打开一个浏览器来在浏览器窗口中运行 PHP 并进行调试:

http://myserver/wsdemo/websockets2.php?debug=1&port=9999 

如果该目录位于您的本地计算机上,您将需要安装 PHP,然后您可以在命令行上运行 websockets2.php 并在浏览器中打开 websockets2.html

请注意,websocket2.php 需要 JSONsvc2.php

在命令行上,您可以通过以下方式更改默认端口(从 12352 开始)并启用调试: 

prompt> php websockets2.php -d -p9999 

在所有情况下,浏览器应用程序都需要知道 websocket 服务器的位置,因此请填写 Websocket Host。一些示例:

ws://myserver:12352/
ws://:9999/  

默认情况下是连接到我桌子上的 Web 服务器,所以您可以尝试简单地浏览到 http://tonywilk.no-ip.org/wsdemo/websocket2.html ——这可能可用,也可能不可用,但值得一试!

最后 

我认为,随着现在与大多数浏览器的兼容性,我们将看到 Websockets 在各种 Web 应用程序中得到更广泛的应用。然而,当前版本仍然很年轻,有些部分引起了安全方面的担忧(例如用于防止缓存中毒的数据掩码,坦率地说,这很可笑),所以我相信它很快就会改变。

最终甚至可能存在用于 Websockets 的标准化协议。

在此期间,请获取代码,运行服务器,打开浏览器,然后玩玩吧!

TonyWilk  


注释

支持 Websockets v13 的浏览器
撰写本文时,已使用此代码测试了以下浏览器:
PC:Internet Explorer 11,Chrome 32,Firefox 26.0;Android:Chrome 31,Opera 18。
在 Windows PC/笔记本电脑、三星 S3/4、亚马逊 Fire 和 Nexus 7 上。

Websocket 标准

Websocket 标准》定义了“Sec-WebSocket-Version: 13”,如果您看到指向更高版本号的引用,请检查它们是否是指较早的草案。成为“The Websocket Protocol”第 13 版的文档称为:“draft-ietf-hybi-thewebsocketprotocol-17” (!)





© . All rights reserved.