NGINX 监听 websocket 客户端的调用

Posted

技术标签:

【中文标题】NGINX 监听 websocket 客户端的调用【英文标题】:NGINX listen websocket client's call 【发布时间】:2017-11-26 01:21:09 【问题描述】:

我在 Ubuntu 14.04 LTS 机器上有一个简单的 nodejs。 即使客户端在 localhost:3000 上,如何配置 nginx 或乘客来监听对 ws://localhost:8443/helloworld 的调用?

server.js 看起来像:

var path = require('path');
var ws = require('ws');
var express = require('express');
var minimist = require('minimist');
var url = require('url');
var fs    = require('fs');
var http = require('http');
var app = express();

app.use(express.static(path.join(__dirname, 'static')));

/* ======================================== */
/* =======                         ======== */
/* =======    WEBSOCKETS SERVER    ======== */
/* =======                         ======== */
/* ======================================== */

var asUrl = url.parse("http://localhost:8443/");
var port = asUrl.port;
var server = http.createServer(app).listen(port, function() 
    console.log('********** WS HTTP SERVER STARTED********** ');
);

var wss = new ws.Server(
    server : server,
    path : '/helloworld'
);

/* ======================================== */
/* =========    WSS ON CONNETION   ======== */
/* ======================================== */
wss.on('connection', function(ws) 

    console.log('**** CONNECTION RECEIVED =D');
    ws.send(JSON.stringify("WELCOME FROM SERVER =D"));

    ws.on('message', function incoming(data) 
        console.log('********** RECEIVED MSG '+data);
        ws.send(JSON.stringify(data));
    );
);
/* ======================================== */

在我的 static/index.html 文件中,我有:

<!-- ======================================= -->
<!-- ==========       CSS        =========== -->
<!-- ======================================= -->
  <style>
    p  line-height:18px; 
    div  width:500px; margin-left:auto; margin-right:auto;
    #content  padding:5px; background:#ddd; border-radius:5px; 
               overflow-y: scroll; border:1px solid #CCC;margin-top:10px; height: 160px; 
    #input_hello  border-radius:2px; border:1px solid #ccc; margin:10px; padding:5px; width:50%; float:left;
    #status  width:88px;display:block;float:left;margin-top:15px; 
  </style>


<!-- ======================================= -->
<!-- ========== JS FOR WEBSOCKET =========== -->
<!-- ======================================= -->
<script type="text/javascript">
    $(document).ready(function () 
    //-- ======================================= --//

            // ======================== //
            // ====== CONNECTION ====== //
            // ======================== //

            var content = $('#content');
            var message = $('#input_hello input[type="text"]').val();
            var ws = new WebSocket('ws://localhost:8443/helloworld');

            ws.onopen = function() 
                alert("YOU ARE CONNECTED WITH WSS!!!!");
            ;

            // ======================== //
            // ====== ON KEY PRESS ==== //
            // ======================== //

            $("#input_hello").keydown(function(event) 
              // ======= IF IS ENTER ===== //
                if (event.keyCode == 13) 
                  ws.send(message);
                  return false;
                 
              // ======================== //
            );

            // ======================== //
            // ====== WS MESSAGE ====== //
            // ======================== //
            ws.onmessage = function(msg) 
                alert("RECEIVED MESSAGE WITH WSS!!!!");
                addMessage(msg.data);
            

            // ======================== //
            // ==== RENDER MESSAGE ==== //
            // ======================== //
            function addMessage(message) 
                content.prepend('<p><span>' + message + '</span></p>');
                $("#input_hello").val("");
            
    //-- ======================================= --//
    );
</script>





<!-- ======================================== -->
<!-- ======================================== -->
<!-- ========           HTML          ======= -->
<!-- ======================================== -->
<!-- ======================================== -->
<h1>HELLO FROM EXPRESS</h1>
<div id="content"></div>
<div>
    <input type="text" id="input_hello" />
</div>
<!-- ======================================== -->

这是我的 etc/nginx/sites-enabled/default 文件:

#===================#
#==== SERVER::80 ===#
#===================#
server 
        listen 80 default_server;
        listen [::]:80 default_server;
        #========================#
        #====    FOR ROOT   =====#
        #========================#
            root /home/deploy/Desktop/NODE_APP/static;
        #========================#
        #==== FOR PASSENGER =====#
        #========================#
            passenger_enabled on;
            passenger_app_env development;
            passenger_app_type node;
            passenger_app_root /home/deploy/Desktop/NODE_APP;
            passenger_startup_file /home/deploy/Desktop/NODE_APP/server.js;
        location / 
                try_files $uri $uri/ =404;
        


#===================#
#=== SERVER 8443 ===#
#===================#
server 
        listen 8443;
        listen [::]:8443;

        #========================#
        #====    FOR ROOT   =====#
        #========================#
            root /nowhere; #========== NO NEED STATIC FILES..(ONLY WS!)
        #========================#
        #==== FOR WEBSOCKETS ====#
        #========================#
        location / 
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Host $http_host;
          proxy_redirect off;
          proxy_pass http://localhost:8443/helloworld;
        


#=======================================#
#=======================================#

当我运行node /home/deploy/Desktop/NODE_APP/server.js 时,我可以访问 localhost:3000 或 localhost:8443 并通过 ws://localhost:8443/helloworld 上的 websockets 连接到运行在 8443 上的 node.js 服务器。

但是当我运行 sudo service nginx start 时,我无法再与运行在 ws://localhost:8443/helloworld 的 8443 上的 node.js 服务器交换 websockets

如何配置 nginx 或乘客来监听呼叫 ws://localhost:8443/helloworld,即使客户端在localhost:3000上?

【问题讨论】:

您的快速应用程序是仅通过 websocket 处理请求,还是也在端口 80 服务器上处理一些请求?看起来这可以简化一点,但我想检查一下。 感谢@CamdenNarzt 的回答。我要写大写,这样任何人都可以看到:我有一个主服务器在端口 3000 上运行。我使用这个快速服务器作为静态文件的独立服务器,在端口 8443(作为 HTTP)上运行,在这里我创建一个 WS 连接监听ON 8443/helloworld。 我如何配置 NGINX,在端口 8443/helloworld 上侦听第二台服务器,仅用于 WS 数据,而不是用于渲染任何 HTML 页面等。我想保持在主服务器视图上。 拜托,只是一个建议,我认为帮助每个人的最佳方法是一种适用于 HTTP 或 HTTPS 连接的解决方案。如果他更喜欢 SSL,则仅取决于用户所需的配置。但是 NGINX 代理可以是抽象的! 问题是我不断收到 EADDRINUSE 8443,地址已在使用中。但我不能依靠 Cluster 或 pm2 来解决这个问题。我认为是关于 NGINX PROXY 【参考方案1】:

你不能让你的应用和 nginx 在同一个端口上监听。您需要您的应用在另一个端口上侦听 websocket 连接,并让 nginx 从 8443 转发到该端口。

此外,如果您在应用程序中使用多个端口,您需要告诉乘客哪个是“主要”端口:https://www.phusionpassenger.com/library/indepth/nodejs/reverse_port_binding.html#caveat-multiple-http-server-objects-error-http-server-listen-was-called-more-than-once

【讨论】:

完美!非常感谢@CamdenNarzt !!你有什么想分享的例子吗?

以上是关于NGINX 监听 websocket 客户端的调用的主要内容,如果未能解决你的问题,请参考以下文章

WebSocket 客户端的状态不会因网络丢失而改变

python 实现websocket

Java WebSocket 获取客户端的专有名称

使用 Glassfish + Nginx + Javascript 的 Websocket

如何在WebSocket的服务器侧检测客户端的断开连接

从 Silverlight 客户端示例代码调用 WebSocket?