简单了解一下 WebSocket

现在,很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

在这种情况下,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

WebSocket一种在单个 TCP 连接上进行全双工通讯的协议。使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

以上信息摘自维基百科(https://zh.wikipedia.org/wiki/WebSocket)

简单点说,WebSocket 就是减小客户端与服务器端建立连接的次数,减小系统资源开销,只需要一次 HTTP 握手,整个通讯过程是建立在一次连接/状态中,也就避免了HTTP的非状态性,服务端会一直与客户端保持连接,直到你关闭请求,同时由原本的客户端主动询问,转换为服务器有信息的时候推送。当然,它还能做实时通信、更好的二进制支持、支持扩展、更好的压缩效果等这些优点。

推荐一个知乎上叫 Ovear 的网友关于 WebSocket 原理的回答,嘻哈风格科普文,简直不要更赞了!地址:https://www.zhihu.com/question/20215561/answer/40316953

ws 和 wss 又是什么鬼?

Websocket使用 wswss 的统一资源标志符,类似于 HTTPHTTPS,其中 wss 表示在 TLS 之上的 Websocket ,相当于 HTTPS 了。如:

ws://example.com/chat
wss://example.com/chat

默认情况下,Websocket 的 ws 协议使用 80 端口;运行在TLS之上时,wss 协议默认使用 443 端口。其实说白了,wss 就是 ws 基于 SSL 的安全传输,与 HTTPS 一样样的道理。

如果你的网站是 HTTPS 协议的,那你就不能使用 ws:// 了,浏览器会 block 掉连接,和 HTTPS 下不允许 HTTP 请求一样,如下图:

Mixed Content: The page at 'https://domain.com/' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://x.x.x.x:xxxx/'. This request has been blocked; this endpoint must be available over WSS.

这种情况,毫无疑问我们就需要使用 wss:\\ 安全协议了,我们是不是简单的把 ws:\\ 改为 wss:\\ 就行了?那试试呗。

改好了,报错啦!!!

VM512:35 WebSocket connection to 'wss://IP地址:端口号/websocket' failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR

很明显 SSL 协议错误,说明就是证书问题了。记着,这时候我们一直拿的是 IP地址 + 端口号 这种方式连接 WebSocket 的,这根本就没有证书存在好么,况且生成环境你也要用 IP地址 + 端口号 这种方式连接 WebSocket 吗?肯定不行阿,要用域名方式连接 WebSocket 阿。

Nginx 配置域名支持 WSS

不用废话,直接在配置 HTTPS 域名位置加入如下配置:

location /websocket {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

接着拿域名再次连接试一下,不出意外会看 101 状态码:

这样就完成了,在 HTTPPS 下以域名方式连接 WebSocket ,可以开心的玩耍了。

稍微解释一下 Nginx 配置

Nginx 自从 1.3 版本就开始支持 WebSocket 了,并且可以为 WebSocket 应用程序做反向代理和负载均衡。

WebSocket 和 HTTP 协议不同,但是 WebSocket 中的握手和 HTTP 中的握手兼容,它使用 HTTP 中的 Upgrade 协议头将连接从 HTTP 升级到 WebSocket,当客户端发过来一个 Connection: Upgrade请求头时,Nginx 是不知道的,所以,当 Nginx 代理服务器拦截到一个客户端发来的 Upgrade 请求时,需要显式来设置ConnectionUpgrade 头信息,并使用 101(交换协议)返回响应,在客户端和代理服务器、后端服务器之间建立隧道来支持 WebSocket。

当然,还需要注意一下,WebSockets 仍然受到 Nginx 缺省为60秒的 proxy_read_timeout 的影响。这意味着,如果你有一个程序使用了 WebSockets,但又可能超过60秒不发送任何数据的话,那你要么需要增加超时时间,要么实现一个 ping 的消息以保持联系。使用 ping 的解决方法有额外的好处,可以发现连接是否被意外关闭。

更具体文档详见 Nginx 官方文档:http://nginx.org/en/docs/http/websocket.html

总结一下

这一篇文章主要了解一下 WebSocket 基本原理和一些使用用途,并解决在实际开发使用过程中遇到的坑,HTTPS 下使用 wss 协议的问题,以及配合 Nginx 使用域名方式建立连接,不使用 IP地址 + 端口号 连接 WebSocket,因为这种方式不够优雅。

下一篇,全站升级 HTTPS 之路,并没你想象的那么简单。

WebSocket 结合 Nginx 实现域名及 WSS 协议访问的更多相关文章

  1. WebSocket 结合 Nginx 实现域名及 WSS 协议访问-Nginx配置

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  2. 关于配置websocket,nginx转发https至wss问题

    在本地测试通过的socket,再放到现在的有nginx代理之后发现会报:failed: Error in connection establishment: net::ERR_NAME_NOT_RES ...

  3. 微信小程序配置WSS协议

    配置的是nginx转发,前提是你已经安装了nginx的软件并已经正常打开网页,安装好SSL协议,能打开https网页 下面是配置: 需要的话可以根据需求修改 server { listen 80; s ...

  4. vps被封逃逸_v2+cloudflare+websocket+tls+nginx

    每逢重大节日,总有那么一大部分vps凉凉,以下为能正经正常使用vps,无奈之举,此法由于多层代理,夜间速度会有影响,白天感受不明显. 由于博客园内容审查,v2_ray 中间的 下划线为分隔符,相关链接 ...

  5. V2Ray+WebSocket+TLS+Nginx 配置及使用

    v2ray 是一个模块化的代理工具,支持 VMess,Socks,HTTP,Shadowsocks 等等协议,并且附带很多高级功能,HTTP,TLS 等等. 关键词限制,全文 v2ray 中的 y 为 ...

  6. Nginx二级域名及多Server反向代理配置

    Nginx强大的正则表达式支持,可以使server_name的配置变得很灵活,如果你要做多用户博客,那么每个用户拥有自己的二级域名也就很容易实现了. 注:nginx反向代理同一ip多个域名,给head ...

  7. nginx搭建http和rtmp协议的流媒体服务器

    nginx搭建http和rtmp协议的流媒体服务器 时间:2013-09-23 23:52来源:佚名 作者:本站 举报 点击:232次 实验目的:让Nginx支持flv和mp4格式文件,同时支持Rtm ...

  8. 【转】Linux下nginx配置https协议访问的方法

    一.配置nginx支持https协议访问,需要在编译安装nginx的时候添加相应的模块--with-http_ssl_module 查看nginx编译参数:/usr/local/nginx/sbin/ ...

  9. nginx二级域名配置

    CentOs下nginx二级域名配置 域名配置文件 命名规则:XXX.域名信息.conf 配置文件路径:etc/nginx/conf.d/xxxx.conf 配置文件内容:server { liste ...

随机推荐

  1. java集合系列—ArrayList

    ArrayList是工作以来使用频率最高的集合类.以前上课老师说不知道用什么集合类就用ArrayList,好吧,后面就这样了. public class ArrayList<E> exte ...

  2. ubuntu16.04 编译运行 LSD-SLAM

    下载编译LSDSLAM,可能会出现 CreateGlutWindowAndWind is not a member of pangolin 以及 该函数参数报错的问题: 原因是在新的pangolin版 ...

  3. Microsoft Windows 2003 SP2 - 'ERRATICGOPHER' SMB Remote Code Execution

    EDB-ID: 41929 Author: vportal Published: 2017-04-25 CVE: N/A Type: Remote Platform: Windows Aliases: ...

  4. 用css3动画 @keyframes里设置transform:rotate(); 控制动画暂停和运动用属性:animation-play-state:paused暂停,在微信和safari里设置paused无效,在QQ里是正常的

    这几天遇到了两个很奇葩的问题,终于找到原因,趁还记得解决方法,赶紧记下来: 用css3动画 @keyframes里设置transform:rotate(); 控制动画暂停和运动可以用属性:animat ...

  5. Spring MVC 请求处理流程概览

    SpringMVC工作流程 图一:请求流程概述 图二:请求在每个组件的处理 解释Spring工作流程 1.用户向服务器发送请求,请求被spring前端控制Servelt DispatcherServe ...

  6. Struts2 控制文件上传下载

    之前介绍servlet3.0新特性的时候有提到过servlet API提供了一个part类来实现对文件的上传和保存,Struts其实是在其基础上做了进一步的封装,更加简单易用.至于文件下载,Strut ...

  7. 第 16 章 MySQL Cluster

    前言: MySQL Cluster 是一个基于 NDB Cluster 存储引擎的完整的分布式数据库系统.不仅仅具有高可用性,而且可以自动切分数据,冗余数据等高级功能.和 Oracle Real Cl ...

  8. java虚拟机学习-深入理解JVM(1)

    1   Java技术与Java虚拟机 说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成: Java编程语言.Java类文件格式.Java虚拟机和Java应 ...

  9. Java经典编程题50道之一

    有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? public class Example01 {    publi ...

  10. Jenkins修改管理员密码

    前言:Jenkins修改管理员密码,我看了网上所有的教程,竟然全都是拿着一串已经加密好的111111的密文去替代config.xml文件里面的密码,然后大家的密码都是111111!我觉得这种做法实在太 ...