我已经了解了WebSockets,并且我的新初始计划是创建一个NodeJS服务器与Socket.io一起处理消息(如何集成nodeJS + Socket.IO和PHP?),并考虑将这些消息存储在MySQL数据库中(MySQL with Node.js)。
这是我目前的情况(不多,我想在真正进展之前澄清如何进展)。这是我的测试设置,实际聊天中使用的HTML显然有所不同。
Node.js服务器:
// NODE
var socket = require( 'socket.io' );
var express = require( 'express' );
var https = require( 'https' );
var http = require( 'http'); //Old
var fs = require( 'fs' );
var app = express();
//Working HTTPS server
var server = https.createServer({
key: fs.readFileSync('/etc/letsencrypt/live/%site%/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/%site%/fullchain.pem')
},app);
// var server = https.createServer( app ); Won't work cause no cert.
var io = socket.listen( server );
console.log("Server Started");
io.sockets.on( 'connection', function( client ) {
console.log( "New client !" );
client.on( 'message', function( data ) {
console.log( 'Message received ' + data); //Logs recieved data
io.sockets.emit( 'message', data); //Emits recieved data to client.
});
});
server.listen(8080, function() {
console.log('Listening');
});
JS客户端脚本:
var socket = io.connect('https://%site%:8080');
document.getElementById("sbmt").onclick = function () {
socket.emit('message', "My Name is: " + document.getElementById('nameInput').value + " i say: " + document.getElementById('messageInput').value);
};
socket.on( 'message', function( data ) {
alert(data);
});
我的超级简单的测试HTML:
<form id="messageForm">
<input type="text" id="nameInput"></input>
<input type="text" id="messageInput"></input>
<button type="button" id="sbmt">Submits</button>
</form>
PHP需要一些解释- 当有人连接到我的网站时,我运行session_start()
。这是因为我想要像匿名会话这样的东西。我通过$_SESSION
变量区分已登录和匿名用户。匿名用户将具有设置为true的$_SESSION ['anon']
,并且不会设置$_SESSION ['username']
。已登录用户将明确相反。
当涉及聊天时-对已登录用户和匿名用户均可用。当用户是匿名时,从数据库或随机名称生成随机用户名。当用户登录时,选择他自己的用户名。现在我的Ajax轮询系统工作方式如下:
用户输入消息(在当前聊天解决方案中,而不是我上面发送的测试HTML)并按Enter键,然后发出AJAX调用以下函数:
function sendMessage($msg, $col) {
GLOBAL $db;
$un = "";
if (!isset($_SESSION['username'])) {
$un = self::generateRandomUsername();
} else {
$un = $_SESSION['username'];
}
try {
$stmt = $db->prepare('INSERT INTO chat (id, username, timestamp, message, color) VALUES (null, :un, NOW(), :msg, :col)');
$stmt->bindParam(':un', $un, PDO::PARAM_STR);
$stmt->bindValue(':msg', strip_tags(stripslashes($msg)), PDO::PARAM_STR); //Stripslashes cuz it saved \\\ to the DB before quotes, strip_tags to prevent malicious scripts. TODO: Whitelist some tags.
$stmt->bindParam(':col', $col, PDO::PARAM_STR);
} catch (Exception $e) {
var_dump($e->getMessage());
}
$stmt->execute();
}
(请不要讨厌我的糟糕代码和糟糕的异常处理,这不是任何官方项目)。此函数将用户消息输入数据库。
为了接收新消息,我使用JS的setTimeout()
函数,在新消息后每1秒运行一次AJAX检查。我保存在JS中显示的最后一条消息的ID,并将该ID作为参数发送到此PHP函数(并且每1秒运行一次):
/* Recieve new messages, ran every 1s by Ajax call */
function recieveMessage($msgid) {
//msgid is latest msg id in this case
GLOBAL $db;
$stmt = $db->prepare('SELECT * FROM chat WHERE id > :id');
$stmt->bindParam(':id', $msgid, PDO::PARAM_INT);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return json_encode($result);
}
问题是:如何实现类似的功能,但使用我之前提到的node.js服务器和websockets设置?我需要以某种方式区分已登录用户和匿名用户。我的第一个想法是从node.js服务器运行ajax调用到PHP,并传递消息数据,PHP将像现在一样将其插入DB中。但是,在这种情况下发送消息给客户端的问题是什么?当消息被输入到数据库时应用用户名,这意味着我必须调用AJAX保存到DB,然后调用另一个AJAX提取新输入的消息并将其发射到客户端,或者创建一个函数来插入、提取和返回提取的消息。然而,当同时输入2条消息时,这是否会引起问题?
有没有办法在Node.js中访问PHP会话变量?那么我就可以重写所有DB查询,使其在Node.js服务器而不是PHP中工作。
如果我的代码或解释混乱,请再次原谅。