我一直在玩NodeJS和最近的socket.IO,我来自PHP开发部门,试图真正了解如何使用Node和socket.IO
我开始构建一个聊天应用程序,当我在不同的设备上对其进行测试时,我注意到例如当我通过手机登录另一个帐户时,浏览器窗口会更新并获得与我登录时使用的用户相同的用户。电话
index.html
<!DOCTYPE html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: 0.5%; }
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
</style>
</head>
<body>
<div id="chatLogin">
<input type="text" name="password" id="username" placeholder="Username..." /><br>
<input type="password" name="password" id="password" placeholder="Password..." /><br>
<button id="chatLoginBtn">Login / Register</button>
</div>
<div id="chatWindow">
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
$(function () {
var socket = io();
$(document).ready(function(){
$("#chatWindow").hide();
$("#chatLoginBtn").click(function(){
socket.emit('loginForm', {
username: $("#username").val(),
password: $("#password").val()
});
});
});
socket.on('returnValue', function(msg) {
var html = '<ul id="messages"></ul>' +
'<form id="sendMsg" action="">' +
'<input id="m" autocomplete="off" /><button>Send</button>' +
'</form>';
$("#chatLogin").html("").hide();
$("#chatWindow").html(html).show();
$('#sendMsg').submit(function(e) {
e.preventDefault(); // prevents page reloading
var time = Date.now();
var msg = $("#m").val();
var data = [time, msg];
socket.emit('chat', data);
$('#m').val('');
return false;
});
});
socket.on('chat', function(msg){
$('#messages').append($('<li>').text(msg));
});
});
</script>
</body>
</html>
index.js
var app = require('express')();
var http = require('http').createServer(app);
var phpPass = require('node-php-password');
var mysql = require('mysql');
var io = require('socket.io')(http);
var cookieParser = require('cookie-parser');
var session = require('express-session');
// DECLARE the variables we will be using
// These does not change
let userCount = 0;
// These are declared to be later set
var displayName;
var userDataID;
// POOL MySQL Connection
var pool = mysql.createPool({
connectionLimit : 100,
host : 'localhost',
user : 'root',
password : '....',
port : '3306',
database : '....',
debug : false
});
// session & cookieParser
/*var sessionMiddleware = session({
secret: "keyboard cat"
});
io.use(function (socket, next) {
sessionMiddleware(socket.request, socket.request.res, next);
});
app.use(sessionMiddleware);
app.use(cookieParser());*/
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
var hashPassword;
function checkUser(user, Password, userID) {
pool.getConnection(function(error,connection) {
connection.query("SELECT password FROM accounts WHERE `username` = '"+user+"' LIMIT 1",function(error,rows){
if (!error) {
var hashPassword = rows[0].password;
if (phpPass.verify(Password, hashPassword)) {
console.log(Password);
console.log(hashPassword);
console.log("Went well");
// UPDATE user database with current socketID
connection.query("UPDATE accounts SET `socketID` = '"+userID+"' WHERE `username` = '"+user+"'",function(error,result){
connection.release();
if (!error) {
connection.query("SELECT id,displayName,username,email,fullName,dateofBirth,created,lastSignedIn FROM accounts WHERE socketID = '"+userID+"' LIMIT 1",function(error,userData){
if (!error) {
displayName = userData[0].displayName;
userDataID = userData[0].id;
console.log("Current user: " + userData[0].displayName);
} else {
console.log("Error" + error);
}
});
console.log("No error" + result);
} else {
console.log("We found error" + error);
}
});
// send to function to gather all needed info from database and save for the current session
return true;
} else {
console.log("Wrong pass");
return false;
}
console.log(hashPassword);
} else {
console.log(error);
return false;
}
});
connection.on('error', function(error) {
});
});
return true;
};
io.on('connection', (socket) => {
var req = socket.request;
var userID = socket.id;
// When connection is inited
userCount++;
console.log('User connected' + userCount);
// Take the data from login and pass to check if it is valid
socket.on("loginForm", function(data){
const user = data.username,
pass = data.password;
//console.log(checkUser(user, pass));
if (checkUser(user, pass, userID)) {
io.emit('returnValue', 'hi');
}
});
function joinRoom(room) {
socket.join(room);
console.log("Joined " + room);
return io.emit('chat', "Joined new room " + room);
}
socket.on('join', (data) => {
socket.join(data);
console.log("Joined " + data);
});
socket.on('chat', (data) => {
/* Array: Data;
[0] Time
[1] Message
[2] socketID
[3] User
*/
var msg = data[1];
var time = data[0];
// Calc time
var date = new Date(time);
var hours = date.getHours();
var minutes = date.getMinutes();
var formatted = hours + ":" + minutes;
if (minutes < 10) return minutes = "0" + minutes;
var dateFormatted = "[" + formatted + "] ";
//data.push(user);
pool.getConnection(function(error,connection) {
connection.query("INSERT INTO `chat_messages` (userID, socketID, message, time) VALUES ('"+userDataID+"', '"+userID+"', '"+msg+"', '"+time+"')",function(error,rows){
connection.release();
if (!error) {
console.log("Success");
} else {
console.log(error);
}
});
});
if (msg.startsWith('/me')) return io.emit('chat', dateFormatted + displayName + msg.substring(3));
if (msg.startsWith('/join')) return joinRoom(msg.substring(6));
if (msg.startsWith('/rooms')) return console.log(io.sockets.adapter.rooms);
return io.emit('chat', dateFormatted + displayName + ' said: ' + msg);
//console.log(displayName + 'said:' + msg);
});
// When user disconnects
socket.on('disconnect', () => {
userCount--;
console.log('User disconnected!' + userCount);
});
});
http.listen(3000, () => {
console.log('Listening on *:3000');
});
我没有收到任何错误,它可以正确计算用户数量
问题在于,首次登录的用户切换为最后登录的用户
如何使用户会话唯一,以便可以将多个客户端登录到不同的帐户?
答案 0 :(得分:1)
我注意到一个问题:var userDataID;
这是一个全局变量。每次有新用户登录时,userDataID
都会更新。它始终是最新登录用户的ID。然后,所有新消息将与userDataID一起存储在数据库中。
例如:
-在窗口上通过帐户A登录,userDataID = 1;
-向服务器发送一些消息,这些消息将以userID = 1存储
-在iPhone上通过帐户B登录,userDataID将更新,现在为= 2。
-从windown和iphone发送一些消息。所有这些消息将使用用户ID 2存储。
我认为那是你得到的错误。
应将用户ID存储在cookie或会话中。