概述
本文为WebSocket协议的第四章,本文翻译的主要内容为WebSocket建立连接开始握手的内容,主要包含了客户端和服务端握手的内容,以及双方如何处理相关字段和逻辑。
4 开始握手(协议正文)
4.1 客户端要求
为了建立一个WebSocket连接,客户端需要建立一个连接并且发送一个在本节中定义的握手协议。连接最初状态为CONNECTING。客户端需要提供一个第三章讨论过的主机(host)、端口(port)、资源名称(resource name)和安全标记(secure)字段以及可被使用的一个协议(protocol)和扩展(extensions)列表。另外,如果客户端是一个Web浏览器,还需要提供源(origin)字段。
客户端在一个受控制的环境内运行,如使用特定运营商的手机浏览器,可能会断开连接切换到其他的运营商。在这种情况下,我们需要考虑包括手机软件和相关运营商在内的指定客户端。
当客户端通过一系列的配置字段(主机(host)、端口(port)、资源名称(resource name)和安全标记(secure))以及一个可被使用的协议(protocol)和扩展(extensions)列表来建立一个WebSocket连接,它一定会通过发送一个握手协议,并且受到一个服务端的握手响应来建立一条连接。建立连接具体需要哪些东西,在开始握手的时候会发送哪些字段,如何处理解读服务端的的响应都会在这一部分得到解答。在下面的内容中,我们会使用到第三章定义的一些术语如主机(host)和安全(secure)字段。
1.WebSocket的URI部分传递的字段(主机(host)、端口(port)、资源名称(resource name)和安全标记(secure))必须是在第三章WebSocket URIs部分指定过的有效字段,如果任意部分是无效字段,那么客户端一定会在接下来的步骤中关闭连接。2.如果客户端有一条通过远端主机(IP地址)定义的主机和端口定义的已经建立连接的WebSocket连接,即使这个远端主机被定义为了其他的名字,这个客户端也必须等到当前的这条连接建立成功或者失败才能建立连接。客户端最多有一条连接可以处于CONNECTING状态。如果多个连接尝试同时与一个相同的IP地址建立连接,客户端必须把他们进行排序,所以只能有一个连接执行下面的步骤。如果客户端不能够确定远程主机的IP地址(例如所有的请求都通过一个自己执行DNS查询的代理),那么客户端必须基于此假设每一个主机名都对应着不同的远端主机,因此客户端应该限制同时连接的总数目在一个比较合理的小数目上(例如:客户端可能允许同时跟a.example.com和b.example.com这两个地址建立连接,但是如果同时和主机建立三十个连接,这可能是不允许的)。例如:在Web浏览器环境下,客户端需要考虑在用户打开的多个tab页中设置一个同时建立连接的数目限制。注意:这个限制使得脚本仅仅通过创建大量的WebSocket连接来进行拒绝服务攻击变得更难了。服务端可以在关闭连接前就停止攻击,从而进一步减小负载,这样会减少客户端的重连率。注意:客户端可以与单个主机建立的WebSocket连接数量是没有限制的。当建立的连接过多时,服务端可以拒绝和主机/IP地址建立的连接,同时服务端在负载过高时也可以主动断开占用资源的连接。3.使用代理:如果客户端在使用WebSocket协议来连接特定的主机和端口时使用了配置的代理,那么客户端应该连接到那个代理并且通过这个代理去和指定的主机和端口建立一个TCP连接。例如:如果客户端使用了全局的HTTP代理,那么如果尝试和example.com的80端口建立连接,那么久可能会发送下面的字段给代理服务器:CONNECT example.com:80 HTTP/1.1Host: example.com `````` 如果有密码字段的话,那么可能如下所示: ``````CONNECT example.com:80 HTTP/1.1Host: example.comProxy-authorization: Basic ZWRuYW1vZGU6bm9jYXBlcyE= 如果客户端没有配置代理,那么就应该会和给定的主机和端口直接建立一条TCP连接。注意:如果可以,实现不暴露明显界面的来给WebSocket选择与其他代理分开的代理推荐使用SOCKS5(RFC1928)代理供WebSocket连接,如果不行的话,使用配置了HTTPS连接的代理优于使用HTTP连接的代理。为了自动配置脚本,传递参数的URI必须包含定义在第三节WebSocket URI中的主机(host)、端口(port)、资源名称(resource name)和安全(secure)字段。注意:WebSocket协议可以根据定义的规范配置到代理自动配置脚本("ws"代表非加密连接,"wss"代表加密连接)。4.如果连接没有被打开,或者由于直连失败或者代理返回了一个错误,那么客户端必须断开WebSocket连接,并且停止重试连接。5.如果安全(secure)字段存在,客户端必须在连接建立以后、发送握手数据之前进行