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.