This commit is contained in:
test 2017-06-20 10:32:05 +08:00
parent 254a77b830
commit 38b89d540d
8 changed files with 333 additions and 0 deletions

16
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
// 使 IntelliSense Node.js
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动程序",
"program": "${workspaceRoot}\\index.js",
"protocol": "inspector"
}
]
}

123
lib/chat_server.js Normal file
View File

@ -0,0 +1,123 @@
const
socketio=require('socket.io');
var io,
guestNumber=1, //用户编号
nickNames={}, //socket id对应的nickname
namesUsed={}, //所有已使用的nickname
allRooms={}, //聊天室--人数
currentRoom={}; //sockid--聊天室
module.exports.listen=function(server){
io=socketio.listen(server);
io.serveClient('log level',1);
io.sockets.on('connection',function(socket){
guestNumber=assignGuestName(socket,guestNumber,nickNames);
joinRoom(socket,'Lobby');
handleMessageBroadcasting(socket,nickNames);
handleNameChangeAttempts(socket,nickNames,namesUsed);
handleRoomJoining(socket);
socket.on('rooms',function(){
socket.emit('rooms',JSON.stringify(allRooms));
});
handleClientDisconnection(socket,nickNames,namesUsed);
});
};
//新socket连入自动分配一个昵称
function assignGuestName(socket,guesetNumber,nickNames){
var name='Guest'+guestNumber;
nickNames[socket.id]=name;
socket.emit('nameResult',{
success:true,
name:name
});
namesUsed[name]=1;
return guestNumber+1;
}
//加入某个聊天室
function joinRoom(socket,room){
socket.join(room);
var num=allRooms[room];
if(num===undefined){
allRooms[room]=1;
}else{
allRooms[room]=num+1;
}
currentRoom[socket.id]=room;
socket.emit('joinResult',{room:room});
socket.broadcast.to(room).emit('message',{
text:nickNames[socket.id]+' has join '+room+'.'
});
var usersinRoom=io.sockets.adapter.rooms[room];
if(usersinRoom.length>1){
var usersInRoomSummary='Users currently in '+room+' : ';
for(var index in usersinRoom.sockets){
if(index!=socket.id){
usersInRoomSummary+=nickNames[index]+',';
}
}
socket.emit('message',{text:usersInRoomSummary});
}
}
//修改昵称
function handleNameChangeAttempts(socket,nickNames,namesUsed){
socket.on('nameAttempt',function(name){
if(name.indexOf('Guest')==0){
socket.emit('nameResult',{
success:false,
message:'Names cannot begin with "Guest".'
});
}else{
if(namesUsed[name]==undefined){
var previousName=nickNames[socket.id];
delete namesUsed[previousName];
namesUsed[name]=1;
nickNames[socket.id]=name;
socket.emit('nameResult',{
success:true,
name:name
});
socket.broadcast.to(currentRoom[socket.id]).emit('message',{
text:previousName+' is now known as '+name+'.'
});
}else{
socket.emit('nameResult',{
success:false,
message:'That name is already in use.'
});
}
}
});
}
//将某个用户的消息广播到同聊天室下的其他用户
function handleMessageBroadcasting(socket){
socket.on('message',function(message){
console.log('message:---'+JSON.stringify(message));
socket.broadcast.to(message.room).emit('message',{
text:nickNames[socket.id]+ ': '+message.text
});
});
}
//加入/创建某个聊天室
function handleRoomJoining(socket){
socket.on('join',function(room){
var temp=currentRoom[socket.id];
delete currentRoom[socket.id];
socket.leave(temp);
var num=--allRooms[temp];
if(num==0)
delete allRooms[temp];
joinRoom(socket,room.newRoom);
});
}
//socket断线处理
function handleClientDisconnection(socket){
socket.on('disconnect',function(){
console.log("xxxx disconnect");
allRooms[currentRoom[socket.id]]--;
delete namesUsed[nickNames[socket.id]];
delete nickNames[socket.id];
delete currentRoom[socket.id];
})
}

39
public/css/style.css Normal file
View File

@ -0,0 +1,39 @@
#content{
width:900px;
margin:auto;
}
#messages{
width:700px;
height:300px;
overflow: auto;
background-color: #eee;
margin-bottom: 1em;
margin-right: 10px;
}
#room-list{
float:right;
width:100px;
height:300px;
overflow:auto;
}
#room-list div{
border-bottom: 1px solid #eee;
}
#room-list div:hover{
background-color:#ddd;
}
#send-message{
width:700px;
margin-bottom: 1em;
margin-right: 1em;
}
#help{
font:10px;
}

34
public/index.html Normal file
View File

@ -0,0 +1,34 @@
<!doctype html>
<html>
<head>
<title>Chat</title>
<meta charset="utf-8"/>
<link rel="stylesheet" href="./css/style.css"/>
</head>
<body>
<div id="content">
<div>当前聊天室:<span id="room"></span>&nbsp;&nbsp;&nbsp;&nbsp;我的昵称:<span id="nickName"></span></div>
<div id="room-list"></div>
<div id="messages"></div>
<form id="send-form">
<input id="send-message" type="text"/>
<input id="send-button" type="button" value="发送"/>
</form>
<div id="help">
命令:
<ul>
<li>修改昵称:<code>/nick [username]</code></li>
<li>加入/创建房间:<code>/join [room name]</code></li>
</ul>
</div>
</div>
<script src="/js/jquery-3.1.1.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="/js/init.js"></script>
<script src="/js/chat_ui.js"></script>
<script src="/js/chat.js"></script>
</body>
</html>

40
public/js/chat.js Normal file
View File

@ -0,0 +1,40 @@
var Chat=function(socket){
this.socket=socket;//绑定socket
}
//发送消息
Chat.prototype.sendMessage=function(room,text){
var message={
room:room,
text:text
};
this.socket.emit('message',message);
};
//变更房间
Chat.prototype.changeRoom=function(room){
this.socket.emit('join',{
newRoom:room
});
};
//处理聊天命令
Chat.prototype.processCommand=function(command){
var words=command.split(' ');
var command=words[0].substring(1,words[0].length).toLowerCase();
var message=false;
switch(command){
case 'join':
words.shift();
var room=words.join(' ');
this.changeRoom(room);
break;
case 'nick':
words.shift();
var name=words.join(' ');
this.socket.emit('nameAttempt',name);
break;
default:
message='Unrecognized command.';
break;
}
return message;
};

21
public/js/chat_ui.js Normal file
View File

@ -0,0 +1,21 @@
function divEscapedContentElement(message){
return $('<div></div>').text(message);
}
function divSystemContentElement(message){
return $('<div></div>').html('<i>'+message+'</i>');
}
function processUserInput(chatApp,socket){
var message=$('#send-message').val();
var systemMessage;
if(message.charAt(0)=='/'){
systemMessage=chatApp.processCommand(message);
if(systemMessage){
$('#messages').append(divSystemContentElement(systemMessage));
}
}else{
chatApp.sendMessage($('#room').text(),message);
$('#messages').append(divSystemContentElement(message));
$('#messages').scrollTop($('#messages').prop('scrollHeight'));
}
$('#send-message').val('');
}

56
public/js/init.js Normal file
View File

@ -0,0 +1,56 @@
if(window.WebSocket){
console.log('This browser supports WebSocket');
}else{
console.log('This browser does not supports WebSocket');
}
var socket=io.connect();
$(document).ready(function(){
var chatApp=new Chat(socket);
socket.on('nameResult',function(result){
var message;
if(result.success){
message='You are known as '+result.name+'.';
}else{
message=result.message;
}
console.log("nameResult:---"+message);
$('#messages').append(divSystemContentElement(message));
$('#nickName').text(result.name);
});
socket.on('joinResult',function(result){
console.log('joinResult:---'+result);
$('#room').text(result.room);
$('#messages').append(divSystemContentElement('Room changed.'));
});
socket.on('message',function(message){
console.log('message:---'+message);
var newElement=$('<div></div>').text(message.text);
$('#messages').append(newElement);
$('#messages').scrollTop($('#messages').prop('scrollHeight'));
});
socket.on('rooms',function(rooms){
console.log('rooms:---'+rooms);
rooms=JSON.parse(rooms);
$('#room-list').empty();
for(var room in rooms){
$('#room-list').append(divEscapedContentElement(room+':'+rooms[room]));
}
$('#room-list div').click(function(){
chatApp.processCommand('/join '+$(this).text().split(':')[0]);
$('#send-message').focus();
});
});
setInterval(function(){
socket.emit('rooms');
},1000);
$('#send-message').focus();
$('#send-button').click(function(){
processUserInput(chatApp,socket);
$('#send-message').focus();
});
});

4
public/js/jquery-3.1.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long