2016-05-12 35 views
0

我目前正在研究包含聊天的移动应用程序。 API后端使用Laravel构建,但对于聊天,我们将使用Socket.io。我们正在使用Let's Encrypt的SSL证书将Socket.io与PHP Web应用程序和Nginx集成

我无法使Socket.io正常工作。它似乎连接,因为在页面加载时,“新连接”消息似乎显示在浏览器的控制台中,但我发送的任何消息似乎都没有收到。我认为Nginx的配置可能不正确。

下面是其目前的最低形式的对话脚本:

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'); 
    }); 
}); 

和客户端实现:

<!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> 

这里是我的Nginx的配置:

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; 
    } 
} 

任何想法什么是错误的?

回答

0

最终解决了它。第一个问题是QUEUE_DRIVERBROADCAST_DRIVER都设置为redis,这打破了广播系统 - 它使用PUSH而不是PUBLISH。因此我删除了QUEUE_DRIVER并且正在正确接收消息。

聊天脚本需要使用HTTPS并加载SSL证书:

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); 
}); 

使用secure参数所需要的客户端实现:

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); 
}); 

有一次,我就做这些改变,它工作得很好。