dro80463 2016-05-12 13:24
浏览 103
已采纳

将Socket.io与PHP Web应用程序和Nginx集成

I'm currently working on a mobile app that includes chat. The API backend is built with Laravel, but for the chat we're going to use Socket.io. We're using an SSL certificate from Let's Encrypt

I'm having trouble getting Socket.io working. It does seem to connect because on page load the 'New connection' message appears to show up in the console in the browser, but any messages I send don't seem to be received. I think the Nginx config is probably incorrect.

Here's the chat script in its current minimal form:

var io = require('socket.io')(9000);

io.on('connection', function (socket) {
  io.emit('connected', {'msg': 'Someone has connected'});

  socket.on('messsage', function (data) {
    io.emit('relaymessage', data);
  });

  socket.on('disconnect', function () {
    io.emit('disconnected');
  });
});

And the client-side implementation:

<!DOCTYPE html>
<html>
    <head>
        <title>Laravel</title>

        <link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css">

        <style>
            html, body {
                height: 100%;
            }

            body {
                margin: 0;
                padding: 0;
                width: 100%;
                display: table;
                font-weight: 100;
                font-family: 'Lato';
            }

            .container {
                text-align: center;
                display: table-cell;
                vertical-align: middle;
            }

            .content {
                text-align: center;
                display: inline-block;
            }

            .title {
                font-size: 96px;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="content">
                <div class="title">Chat</div>
                <div id="output"></div>
                <form>
                    <textarea id="message"></textarea>
                    <button id="submit">Submit</button>
                </form>
            </div>
        </div>
        <script type="text/javascript" src="//code.jquery.com/jquery-2.2.3.min.js"></script>>
        <script type="text/javascript" src="/client.js"></script>>
        <script type="text/javascript">
            var socket = io(window.location.href);
            var txt = document.getElementById('message');
            var btn = document.getElementById('submit');
            socket.on('connected', function (data) {
                console.log('New connection');
            });
            socket.on('relaymessage', function (data) {
                console.log(data);
                $('div#output').append('<p>' + data.content + '</p>');
            });
            socket.on('disconnected', function () {
                console.log('Disconnected');
            });
            $('button#submit').on('click', function (event) {
                event.preventDefault();
                var content = $('textarea#message').val();
                socket.emit('message', { content: content });
                $('textarea#message').val('');
            });
        </script>>
    </body>
</html>

Here's my Nginx config:

server {
    listen         80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com.com/privkey.pem;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
    client_max_body_size 50M;
    server_tokens off;
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";

    root /var/www/public;
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
        gzip on;
        gzip_proxied any;
        gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/xml-rss text/javascript text/js application/json;
        expires 1y;
        charset utf-8;
    }

    location ~ \.php$ {
        try_files $uri /index.php =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location /socket.io/ {
        proxy_pass http://localhost:9000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

    location ~ /.well-known {
        root /var/www/public;
        allow all;
    }   
}

Any idea as to what's gone awry?

  • 写回答

1条回答 默认 最新

  • duandu1377 2016-05-15 18:41
    关注

    Solved it in the end. First problem was that QUEUE_DRIVER and BROADCAST_DRIVER were both set to redis, which broke the broadcasting system - it used PUSH instead of PUBLISH. I therefore removed QUEUE_DRIVER and the messages were being received correctly.

    The chat script needed to use HTTPS and load the SSL certificate:

    var fs = require('fs');
    var pkey = fs.readFileSync('/etc/letsencrypt/live/example.com/privkey.pem');
    var pcert = fs.readFileSync('/etc/letsencrypt/live/example.com/fullchain.pem')
    var options = {
      key: pkey,
      cert: pcert
    };
    var app = require('https').createServer(options);
    var io = require('socket.io')(app);
    var Redis = require('ioredis');
    var redis = new Redis();
    app.listen(9000, function() {
        console.log('Server is running!');
    });
    function handler(req, res) {
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.writeHead(200);
        res.end('');
    }
    io.on('connection', function(socket) {
        //
    });
    redis.psubscribe('*', function(err, count) {
        //
    });
    redis.on('pmessage', function(subscribed, channel, message) {
        message = JSON.parse(message);
        console.log('Channel is ' + channel + ' and message is ' + message);
        io.emit(channel, message.data);
    });
    

    The client-side implementation needed to use the secure parameter:

    var url = window.location.protocol + '//' + window.location.hostname;
    var socket = io(url, {
      'secure': true,
      'reconnect': true,
      'reconnection delay': 500,
      'max reconnection attempts': 10
    });
    var chosenEvent = 'room_' + room.id;
    socket.on(chosenEvent, function (data) {
      console.log(data);
    });
    

    Once I'd made those changes, it worked fine.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 在虚拟机中安装flash code
  • ¥15 单片机stm32f10x编写光敏电阻调节3.3伏大功率灯亮度(光强越大灯越暗,白天正常光强灯不亮,使用ADC,PWM等模块)望各位找一下错误或者提供一个可实现功能的代码
  • ¥20 verilog状态机方法流水灯
  • ¥15 pandas代码实现不了意图
  • ¥15 GD32H7 从存储器到外设SPI传输数据无法重复启用DMA
  • ¥25 LT码在高斯信道下的误码率仿真
  • ¥45 渲染完成之后将物体的材质贴图改变,自动化进行这个操作
  • ¥15 yolov5目标检测并显示目标出现的时间或视频帧
  • ¥15 电视版的优酷可以设置电影连续播放吗?
  • ¥50 复现论文;matlab代码编写