赞
踩
公司游戏需要搞个微信小程序版,然后小程序需要用wss协议,即webSocket+ssl,所以记录一下(踩坑的)过程,方便看到这篇文章的人(虽然已经是超过半年以前的事情,实际上老大来问我的时候已经快忘光了,找点时间记录下来免得下次继续忘)
目录
首先,webSocket是什么?其实就是一个协议,要求数据按照这个协议的规则来进行发放。关于ws的东西网上一搜一大把,这里就不再赘述,有兴趣的可以自己去看一下,这里推荐http - WebSocket 详解 - 不挑食的程序员 - SegmentFault 思否https://segmentfault.com/a/1190000012948613
写得很详细
然后这里有大佬造的简易轮子,可惜没用上(76条消息) C++实现WebSocket功能及WebSocket协议详解(附代码)_c websocket_贝松的博客-CSDN博客https://blog.csdn.net/qq_39540028/article/details/104493049
首先,相信看这篇文章的都是有升级wss协议需求的,而不是从头开始构建链接,所以就不说那些了,直接从ws开始。ws其实就握手保证一下链接真实可靠,然后通过这个链接双方互相传输消息,最后交换完消息就挥手关掉链接。具体是怎么实现的呢?
首先,在http的基础下,客户端会向服务端提出升级协议,这时候是明文请求的
- GET / HTTP/1.1
- Host: localhost:8080
- Origin: http://127.0.0.1:3000
- Connection: Upgrade
- Upgrade: websocket
- Sec-WebSocket-Version: 13
- Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw==
实际上这里要关心的是两个点,一个是开头的GET,一个是最后的Sec-WebSocket-Key。因为对我实际做的项目来说,需求是能支持同一个服务器接收来自不同客户端的消息,也就是说支持小程序和普通app的混服,而我们自己本身是用的自用协议,所以在客户端开始握手的时候要判断到底是来自于哪里的消息、接下来采用哪种协议去进行通讯。于是乎就直接判断握手消息是否GET开头,是的话后面开始走WS逻辑,否则走我们原来的自用协议。当然假如你有严格要求,或者怕和正在使用的其他协议发生混淆,全部消息检查一遍也是没问题的,上面是ws的 RFC2616的规定,没啥好说的。
而Sec-WebSocket-Key,这是客户端要求服务端做的一个验证,需要在这串东西后面拼接上258EAFA5-E914-47DA-95CA-C5AB0DC85B11这样一个协议约定的字符串,然后把拼接好的内容先sha1算出来一个哈希值,然后将这个哈希值转成base64字符串,到时候回包能用到。这么做主要是为了向客户端保证自己的确收到了这样一个消息,并且针对这个消息做出回复,保证双方不会被偶然链接影响。
好了,收到客户端ws的请求,现在要回复了。
- HTTP/1.1 101 Switching Protocols
- Connection:Upgrade
- Upgrade: websocket
- Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU=
除了Accept以外的东西实际使用没啥好关心的,照样发出去就行了。
nginx代理其实就是用nginx中转,让前端只向nginx对外端口发消息,nginx处理之后将数据按指定规则发给后端,这里的处理其实也可以包括ssl握手与加密,将前端发过来的WSS处理成WS包,后端只要专心解WS包就好了。
SSL需要一个证书支持,所谓的证书其实就是一个身份证证明你是你自己。假如是用阿里云之类的服务器的,去申请一个自己对应域名的证书就好了,关于证书的部分可以跳过。但是假如是自机测试调试的话,就需要自己弄一个证书给nginx了。
首先要注意一点,wss访问是访问域名的,而证书也是对域名进行认证的。自己本机上调试的怎么办?改个host自己弄个域名就好。C:\Windows\System32\drivers\etc这个路径,或者你是linux的话就etc/hosts,加个
127.0.0.1 test.game.net
将test.game.net定向到本机ip上,当然你自己改个域名也行,不过下面的步骤都要自己跟着改。
域名弄好之后,下个openssl证书开搞,具体可以查看(88条消息) 关于Nginx配置SSL证书(Https)和WebSocket的wss_wss证书_Shiro to kuro的博客-CSDN博客
记得两个点:
1.nginx域名填刚刚host里面改的域名
2.做证书的时候Common Name一定要填那个域名!
给一下我的conf
-
- #user nobody;
- worker_processes 1;
-
- #error_log logs/error.log;
- #error_log logs/error.log notice;
- #error_log logs/error.log info;
-
- #pid logs/nginx.pid;
-
-
- events {
- worker_connections 1024;
- }
-
-
- http {
- include mime.types;
- default_type application/octet-stream;
-
- #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
- # '$status $body_bytes_sent "$http_referer" '
- # '"$http_user_agent" "$http_x_forwarded_for"';
-
- #access_log logs/access.log main;
-
- sendfile on;
- #tcp_nopush on;
-
- #keepalive_timeout 0;
- keepalive_timeout 65;
-
- #gzip on;
-
- server {
- listen 80;
- server_name test.game.net;
-
- #charset koi8-r;
-
- #access_log logs/host.access.log main;
-
- location / {
- root html;
- index index.html index.htm;
- }
-
- #error_page 404 /404.html;
-
- # redirect server error pages to the static page /50x.html
- #
- error_page 500 502 503 504 /50x.html;
- location = /50x.html {
- root html;
- }
-
- # proxy the PHP scripts to Apache listening on 127.0.0.1:80
- #
- #location ~ \.php$ {
- # proxy_pass http://127.0.0.1;
- #}
-
- # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
- #
- #location ~ \.php$ {
- # root html;
- # fastcgi_pass 127.0.0.1:9000;
- # fastcgi_index index.php;
- # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
- # include fastcgi_params;
- #}
-
- # deny access to .htaccess files, if Apache's document root
- # concurs with nginx's one
- #
- #location ~ /\.ht {
- # deny all;
- #}
- }
-
-
- # another virtual host using mix of IP-, name-, and port-based configuration
- #
- #server {
- # listen 8000;
- # listen somename:8080;
- # server_name somename alias another.alias;
-
- # location / {
- # root html;
- # index index.html index.htm;
- # }
- #}
-
- map $http_upgrade $connection_upgrade {
- default upgrade;
- '' close;
- }
-
-
- # HTTPS server
- #
- server {
- listen 443 ssl;
- server_name test.game.net;
-
- ssl_certificate ../keys/server.pem;
- ssl_certificate_key ../keys/server.key;
-
- ssl_session_timeout 5m;
- ssl_session_cache shared:SSL:10m;
- ssl_protocols TLSv1 TLSv1.1 TLSv1.2 SSLv2 SSLv3;
- ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
- ssl_prefer_server_ciphers on;
- ssl_verify_client off;
-
- #location / {
- # root html;
- # index index.html index.htm;
- #}
- location /{
- proxy_redirect off;
- proxy_pass http://本机IP:想要转发的端口/;
- proxy_set_header Host $host;
- proxy_set_header X-Real_IP $remote_addr;
- proxy_set_header X-Forwarded-For $remote_addr:$remote_port;
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection upgrade;
- }
- }
- }
上面最重要的是HTTPS的部分,内容其实就是监听443接口,认为传入的是ssl加密后信息,转发到你自己ip和端口上,然后让你自己的服务端去监听这个端口。
nginx搭起来了,就可以用在线工具测一下了
WebSocket在线测试工具 (wstool.js.org)
只不过浏览器搞的话,因为你的证书是自己当CA签的,浏览器不会认,要先让浏览器放行你的证书。具体操作方法就是开了nginx之后,浏览器上一下监听的域名,然后应该会说网站证书不安全之类的,点一下把你的自签证书加入可信。不然的话用上面的在线工具会报错
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。