websocket

 <!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>聊天</title>
    <link rel="stylesheet" href="">
    <script language="JavaScript" src="http://code.jquery.com/jquery-1.11.0.js"></script>
    <script type="text/javascript">
    </script>
</head>
<style type="text/css" media="screen">
div {
    border: 1px solid #cccccc;
     500px;
    min-height: 100px;
}
</style>

<body>
    <div id="show">
    </div>
    <input type="text" id="message" name="" value="" placeholder="" >
    <a href="javascript:void(0)" onclick="send()">发送</a>
    <a href="javascript:void(0)" onclick="exit()">退出</a>
    <!-- <input type="text" id="token" name="" value="" placeholder="" readonly="false"> -->
</body>
<script type="text/javascript">
        var name;
        name = prompt("请问你叫什么名字?");

        var lockReconnect = false;  //避免ws重复连接
        var ws = null;          // 判断当前浏览器是否支持WebSocket
        var wsUrl = "ws://192.168.70.131:443";
        createWebSocket(wsUrl);   //连接ws
        function createWebSocket(url) {
            try {
                if ('WebSocket' in window) {
                    ws = new WebSocket(url);
                } else if ('MozWebSocket' in window) {
                    ws = new MozWebSocket(url);
                } else {
                    alert("line91");
                }
                initEventHandle();
            } catch (e) {
                reconnect(url);
                console.log(e);
            }
        }

        function initEventHandle() {
            ws.onclose = function () {
                console.log("ws连接关闭!" + new Date().toUTCString());
                reconnect(wsUrl);
            };
            ws.onerror = function () {
                console.log("ws连接错误!");
                reconnect(wsUrl);
            };
            ws.onopen = function () {
                heartCheck.reset().start();      //心跳检测重置
                console.log("ws连接成功!" + new Date().toUTCString());
            };
            ws.onmessage = function (event) {    //
                heartCheck.reset().start();      //
                handMsg(event.data);
            };
        }

        // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function () {
            ws.close();
        }

        function reconnect(url) {
            if (lockReconnect) return;
            lockReconnect = true;
            setTimeout(function () {     //没连接上会一直重连,设置延迟避免请求过多
                createWebSocket(url);
                lockReconnect = false;
            }, 2000);
        }

        //心跳检测
        var heartCheck = {
            //timeout: 540000,        //9分钟发一次心跳
            //timeout: 3600,        //1分钟发一次心跳
            timeout: 10800,        //3分钟发一次心跳
            timeoutObj: null,
            serverTimeoutObj: null,
            reset: function () {
                clearTimeout(this.timeoutObj);
                clearTimeout(this.serverTimeoutObj);
                return this;
            },
            start: function () {
                var self = this;
                //console.log(self.timeout);
                this.timeoutObj = setTimeout(function () {
                    //这里发送一个心跳,后端收到后,返回一个心跳消息,
                    //onmessage拿到返回的心跳就说明连接正常
                    ws.send(JSON.stringify({name:name,procotol:'ping'}));
                    console.log("ping!")
                    self.serverTimeoutObj = setTimeout(function () {
                        ws.close();     
                    },self.timeout)
                },this.timeout)
            }
        }
        //========心跳包重连CODE END============================
        //处理消息
        function handMsg(i) {
                console.log(i);
               (i.indexOf("退出") != -1) || $("#show").append(i + "</br>");
        }
        //处理消息
        function send() {
            var msg = $("#message").val();
            var str = "{name:'" + name + "',msg:'" + msg + "'}";
            //console.log("发送", str);
            ws.send(str);
        };

</script>

</html>
var WebSocketServer = require('ws').Server,  
    wss = new WebSocketServer({  
        port: 4001 //监听接口   
    });
 var clients = {};//用户统计    
// 初始化  
wss.on('connection', function(ws) {  
    ws.on('message', function(jsonStr,flags){
        var obj = eval('(' + jsonStr + ')'); 
        console.log(obj);  
        this.user = obj;  
        if (typeof this.user.msg != "undefined") {  
            wss.broadcast(1,obj);  
        }  
    });  
    //退出聊天  
    ws.on('close', function(close) {  
        try{  
            wss.broadcast(0,this.user.name);  
        }catch(e){  
            console.log('刷新页面了');  
        }  
    });
    //广播  
    wss.broadcast = function broadcast(s,ws) {  
        wss.clients.forEach(function each(client) {  
            if(s == 1){ 
                client.send(ws.name + ":" + ws.msg);  
            }  
            if(s == 0){  
                client.send(ws + "退出聊天室");    
            }   
        });  
    };    
});

nginx 配置

user www-data;
worker_processes auto;

events {
    worker_connections 76834;
    # multi_accept on;
}

http {
    upstream wsbackend {
        server 127.0.0.1:3000;
    }

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   /var/www/html;
            index  index.html index.htm;
        }
    }

    server {
        listen       8090;
        server_name  ws://127.0.0.1;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        location / {
            proxy_pass http://wsbackend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    }

    server {
        listen      443;
        server_name http://192.168.138.1;

        #ssl on;

        #ssl_certificate           /data/release/nginx/1_wx.aaa.top_bundle.crt;
        #ssl_certificate_key       /data/release/nginx/2_wx.aaa.top.key;
        #ssl_session_timeout       5m;
        #ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
        #ssl_ciphers               ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA#256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
        #ssl_session_cache         shared:SSL:50m;
        #ssl_prefer_server_ciphers on;

        location / {
            #proxy_pass http://app_weapp;
            proxy_pass http://192.168.70.1:4001;
            proxy_http_version 1.1;
            proxy_send_timeout 6000000s;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
             #proxy_set_header Connection $connection_upgrade;      
        }

      }
}
原文地址:https://www.cnblogs.com/lujiang/p/8657302.html