nginx 作为websocket代理服务器(译)

把服务端与客户端的连接从HTTP/1.1 转化到WebSocket,这需要用到protocol_switch  这个指令。

然而“Upgrade” 是一个hop-by-hop(逐个跳转扩展头),它是不可能通过代理服务器的,虽然客户端或许可以使用CONNECT方法避开这个问题,但是这不适用于反向代理服务器,因为客户端根本不会意识到这个是代理服务器,所以需要一种特殊的方式。

从1.3.13版,nginx实现了一种特殊的机制,只要代理服务器返回101(转换协议)就允许代理服务器和客户端之间建立一个通道,并且客户端会请求通过在请求中添加Upgrade 头来转换协议。

上文提到,包含了“Upgrade”和”Connection”的hop-by-hop 头是不能传到代理服务器的,因此为了通知服务器客户端想要将协议转换到WebSocket,这些头必须显式的传递。

location /chat/ {

    proxy_pass http://backend;

    proxy_http_version 1.1;

    proxy_set_header Upgrade $http_upgrade;

    proxy_set_header Connection “upgrade”;

}

一个发往服务端的的header头中Connection的值 取决于于客户端请求头里面的Upgrade的有无。

http {

    map $http_upgrade $connection_upgrade {

        default upgrade;

              close;

    }

    server {

       

        listen       8070;

        location /chat/ {

            proxy_pass http://127.0.0.1:8010;

            proxy_http_version 1.1;

            proxy_set_header Upgrade $http_upgrade;

            proxy_set_header Connection $connection_upgrade;

        }

    }

此时,对应的服务端代码为,服务端,需要安装nodejs,并且node node.js 运行起来,坚挺8010端口

/*************************************************************************

  * File Name :  node.js

  * Author  :      unasm

  * Mail :         unasm@sina.cn

  * Last_Modified: 2015-05-25 09:56:26

************************************************************************/

console.log(“Server started”);

var connects = new Array();

var WebSocketServer = require(‘ws’).Server

, wss = new WebSocketServer({port: 8010});

console.log(“complete”);

wss.on(‘connection’, function(ws) {

        connects.push(ws);

        ws.on(‘message’, function(msg) {

                ws.send(msg);

                for(var i = 0,len = connects.length; i < len;i++){

                        if(connects[i] !== ws){

                                connects[i].send(msg);

                        }

                }

        });

        console.log(“connection”);

});

客户端html代码为:

 

<html><head></head><body>

                <script type=”text/javascript”>

                        var sock = null;

                        var wsuri = “ws://127.0.0.1:8070/chat/”;

                        window.onload = function() {

                                console.log(“onload”);

                                sock = new WebSocket(wsuri);

                                sock.onopen = function() {

                                        console.log(“connected to ” + wsuri);

                                }

                                sock.onclose = function(e) {

                                        console.log(“connection closed (” + e.code + “)”);

                                }

                                sock.onmessage = function(e) {

                                        console.log(“message received: ” + e.data);

                                }

                        };

function send() {

        var msg = document.getElementById(‘message’).value;

        sock.send(msg);

};

</script>

<h1>WebSocket Echo Test</h1>

<form>

        <p>

        Message: <input id=”message” type=”text” value=”Hello, world!”>

        </p>

</form>

<button onclick=”send();”>Send Message</button>

</body>

</html>

 

原文参考连接http://nginx.org/en/docs/http/websocket.html?_ga=1.166503037.270828851.1426754420

Leave a comment

Your email address will not be published.

*