我目前正在开发包含聊天功能的移动应用。 API后端是用Laravel构建的,但是对于聊天我们将使用Socket.io。我们正在使用Let's Encrypt的SSL证书
我无法让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 :(得分:0)
最终解决了它。第一个问题是QUEUE_DRIVER
和BROADCAST_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);
});
一旦我做了这些改动,它就运行良好。