websocket的应用
实时推送消息,减少网络流量,实质是一个tcp
的长连接.
一般本地开发,不是http
的协议,所以使用的websocket
是以ws://
协议形式的.
当放到生产,若开启了https
,则应该是以wss://
形式的协议.
但是仅仅更改这个协议头是不行的.错误的websocket
地址可能会导致如下报错:
WebSocket connection to ‘wss://example.com:8088/websocket’ failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR
主要原因
- ws
基于
http
下的一种协议,默认的服务端口是80
. - wss
基于
https
下的一种协议,默认的服务端口是433
,如果使用wss
则也需要使用433
的端口号而不是80
,因为我们的SSL
证书配置的都是针对433
端口的. 这个才是原因所在.
如何挖的坑
- 本地开发,一般都是使用的
http
于是前端这样写:var myWebSocket,webSocketUrl='ws://localhost:8080/websocket' if ('WebSocket' in window) { myWebSocket = new WebSocket(webSocketChenkunUrl); } else if ('MozWebSocket' in window) { myWebSocket = new MozWebSocket(webSocketChenkunUrl); } else { alert( 'not support'); }
- 部署到服务器上,因为地址跟端口不固定,于是自作聪明通过一个请求从服务端返回
webSocketUrl
:... @RequestMapping("/ws/getServer") public Result<String> getServer(HttpServletRequest request) { String serverEndPoint = "/websocket"; String server = String.format("ws://%s:%s%s", request.getServerName(), request.getServerPort(), serverEndPoint); LOGGER.debug("get ws server,return:{}", server); return new Result<>(server); } ...
- 服务器使用
https
为了兼容本地与服务端,针对request.getScheme()
判断请求是http
还是https
,判断失败,原因是通过了nginx
反向代理指向的是服务器地址,所有请求在服务端的感知下都是http
的. 使用其他header
进行判定,进而在生产上返回wss://
的协议地址. 测试报错如下: WebSocket connection to ‘wss://example.com:80/websocket’ failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR - 解决:
因为
https
协议是在433
端口,所以wss://
协议的地址也应该是433
.