node.js 聊天室 android,Nodejs实现多房间简易聊天室功能

1、前端界面代码

前端不是重点,够用就行,下面是前端界面,具体代码可到github下载。

2、服务器端搭建

本服务器需要提供两个功能:http服务和websocket服务,由于node的事件驱动机制,可将两种服务搭建在同一个端口下。

1、包描述文件:package.json,这里用到了两个依赖项,mime:确定静态文件mime类型,socket.io:搭建websocket服务,然后使用npm install 安装依赖

{

"name": "chat_room",

"version": "1.0.0",

"description": "this is a room where you can chat with your friends",

"main": "index.js",

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1"

},

"author": "sfs",

"license": "ISC",

"dependencies": {

"socket.io":"2.0.3",

"mime":"1.3.6"

}

}

2、http服务器

http服务主要是给web浏览器提供静态文件,既浏览器发来一个请求,服务器返回一个响应。

const

http=require('http'),

fs=require('fs'),

path=require('path'),

mime=require('mime'),

chatServer=require('./lib/chat_server');

var cache={};//缓存静态文件内容

//发送错误响应

function send404(response){

response.writeHead(404,{'Content-Type':'text/plain'});

response.write('Error 4.4:文件未找到。');

response.end();

}

//发送文件内容

function sendFile(response,filePath,fileContents){

response.writeHead(

200,

{"content-Type":mime.lookup(path.basename(filePath))}

);

response.end(fileContents);

}

//查找文件

function serveStatic(response,cache,absPath){

if(cache[absPath]){

sendFile(response,absPath,cache[absPath]);

}else{

fs.exists(absPath,function(exists){

if(exists){

fs.readFile(absPath,function(err,data){

if(err){

send404(response);

}else{

cache[absPath]=data;

sendFile(response,absPath,data);

}

});

}else{

send404(response);

}

});

}

}

//入口

var server=http.createServer(function(request,response){

var filePath=false;

console.log(`new request for ${request.url}`);

if(request.url==='/'){

filePath='public/index.html';

}else{

filePath='public'+request.url;

}

var absPath='./'+filePath;

serveStatic(response,cache,absPath);

});

server.listen(3000,function(){

console.log("the server is listening on prot 3000.");

});

chatServer.listen(server); //websocket服务也绑定到该端口上

3、socket服务

socket.io提供了开箱既用的虚拟通道,所以不需要任务手动转发消息到已连接的的用户,可以使用 socket.broadcast.to(room).emit('message','hello'); room为某个聊天室id

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

})

}

3、客户端实现socket.io

1、chat.js处理发送消息,变更房间,聊天命令。

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;

};

2、chat_ui.js 处理用户输入,根据输入调用chat.js的不同方法发送消息给服务器

function divEscapedContentElement(message){

return $('

}

function divSystemContentElement(message){

return $('

'+message+'');

}

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

}

3、init.js客户端程序初始化 创建一个websocket连接,绑定事件。

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=$('

$('#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);

});

});

完整代码,可到https://github.com/FleyX/ChatRoom 下载。

以上所述是小编给大家介绍的Nodejs实现多房间简易聊天室功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持! ad51e517755f8fd6a7ec83ced4ecfaf3.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值