参照网上的各种教程和代码实现一个简易在线聊天器,支持定向发消息
服务器端
app.js(使用express搭建静态服务,socket.io建立服务器端监听)
var app = require('express')() , express = require('express') , server = require('http').createServer(app) , io = require('socket.io').listen(server); var zTool = require("./zTool"); var onlineUserMap = new zTool.SimpleMap(); var historyContent = new zTool.CircleList(100); EVENT_TYPE = { "LOGIN":"LOGIN", "LOGOUT":"LOGOUT", "CHAT":"CHAT", "ERROR":"ERROR" }; server.listen(80); app.use('/', express.static(__dirname + '/')); io.sockets.on('connection', function (socket){ // // exception from clients // socket.on("disconnect", function (){ var user = onlineUserMap.get(socket.id); var data = JSON.stringify({ "event":EVENT_TYPE.LOGOUT, "values":[user] }); onlineUserMap.remove(socket.id); io.sockets.emit("message",data);//broadcast }); // // normal messages(login | logout | chat) // socket.on('message', function (message){ //json decode var msgData = JSON.parse(message); if(msgData && msgData.event){ switch(msgData.event) { // //user login // case EVENT_TYPE.LOGIN: var newUser = {"uid":socket.id, "nick":msgData.values[0]}; onlineUserMap.put(socket.id, newUser); var data = JSON.stringify({ "user":onlineUserMap.get(socket.id), "event":EVENT_TYPE.LOGIN, "values":[newUser], "users":onlineUserMap.values(), "historyContent":historyContent.values() }); io.sockets.emit("message",data);//broadcast break; // //user chat // case EVENT_TYPE.CHAT: var content = msgData.values[0]; var data = JSON.stringify({ "user":onlineUserMap.get(socket.id), "event":EVENT_TYPE.CHAT, "values":[content] }); var to = msgData.to; if(to != 0){//private chat io.sockets.emit(socket.id,data); //to sender io.sockets.emit(to,data);//to receiver } else{//public chat io.sockets.emit("message",data);//broadcast historyContent.add({ "user":onlineUserMap.get(socket.id), "content":content, "time":new Date().getTime() }); } break; // //user logout // case EVENT_TYPE.LOGOUT: var user = msgData.values[0]; onlineUserMap.remove(user.uid); var data = JSON.stringify({ "event":EVENT_TYPE.LOGOUT, "values":[user] }); io.sockets.emit("message",data);//broadcast break; } } else { console.log("invalid message , userId:"+socket.id+" , message:"+message); var data = JSON.stringify({ "uid":socket.id, "event":EVENT_TYPE.ERROR }); socket.emit(socket.id, data); } }); });
网页端index.html
<html> <head> <title>chatroom</title> <meta charset="utf-8" /> <script src="jquery.js"></script> <script src="zTool.js"></script> <script src="DateUtil.js"></script> <script src="chat.js"></script> <script src="http://127.0.0.1:80/socket.io/socket.io.js"></script> <link href="style.css" rel="stylesheet" media="all"> </head> <body> <div id="errorPage" class="page" style="display:none"> <h1>当前浏览器不支持WebSocket,请使用其他浏览器,例如chrome 4.0.249.0 +</h1> </div> <div id="prePage" class="page" style="text-align:center;"> <input id = "nickInput" type="text" class="itext" placeholder="输入昵称" style="margin-top:150px;" /> <input id = "enter" type="button" class="ibutton" value="开始聊天" /> </div> <div id="mainPage" class="page" style="display:none"> <div> <div class="talkLeft"> <div id="talkFrame" class="talkHistory"> </div> </div> <div class="talkRight"> <div id="onlineUsers"></div> </div> </div> <div id="inputDiv" style="margin-top:50px"> <input placeholder="说点什么" id="message" class="itext" /> <input type="button" class="ibutton" value="发送" id="send" /> <input type="button" class="ibutton" value="退出" id="logout" /> <select style="float:right" id="chatWith" class="iselect"> <option>所有人</option> </select> </div> </div> </body> </html>
网页端chat.js(监听各种消息,监听服务器异常断开等)
EVENT_TYPE = { "LOGIN":"LOGIN", "LOGOUT":"LOGOUT", "CHAT":"CHAT", "ERROR":"ERROR" }; $(document).ready(function() { var socket = null; var onlineUserMap = new zTool.SimpleMap(); var currentUser = null; var currentUserNick = null; if (typeof WebSocket === 'undefined') { $("#prePage").hide(); $("#errorPage").show(); } function appendMessage(msg) { $("#talkFrame").append("<div>" + msg + "</div>"); document.getElementById("talkFrame").scrollTop = document.getElementById("talkFrame").scrollHeight; } function formatUserTalkString(user) { return user.nick + " " + new Date().format("hh:mm:ss") + " "; } function formatUserTalkHisString(user, time) { return user.nick + " " + new Date(time).format("yyyy-MM-dd hh:mm:ss") + " "; } function reset() { if (socket) { socket.close(); } socket = null; onlineUserMap = null; currentUser = null; $("#onlineUsers").html(""); $("#talkFrame").html(""); $("#nickInput").val(""); $("#chatWith").val("<option>所有人</option>"); } function setChatWith(uid){ $("#chatWith").find(uid).attr("SELECTED","SELECTED"); } function updateOnlineUser() { var html = ["<div>在线用户(" + onlineUserMap.size() + ")</div>"]; if (onlineUserMap.size() > 0) { var users = onlineUserMap.values(); var number = users.length; for ( var i=0;i<number;i++) { html.push("<div>"); if (users[i].uid == currentUser.uid) { html.push("<b>" + users[i].nick + "(我)</b>"); } else { html.push(users[i].nick); } html.push("</div>"); } } $("#onlineUsers").html(html.join('')); } function updateChatWith() { var html = ["<option value=\"0\">所有人</option>"]; if (onlineUserMap.size() > 0) { var users = onlineUserMap.values(); var number = users.length; for ( var i=0;i<number;i++) { if (users[i].uid == currentUser.uid) { } else { html.push("<option value=\""+users[i].uid+"\">"); html.push(users[i].nick); html.push("</option>"); } } } $("#chatWith").html(html.join('')); } //enter chatroom $("#enter").click(function(event) { currentUserNick = $.trim($("#nickInput").val()); if ('' == currentUserNick) { alert('请先输入昵称'); return; } $("#prePage").hide(); $("#mainPage").show(); reset(); socket = io.connect('http://127.0.0.1'); onlineUserMap = new zTool.SimpleMap(); socket.on('connect', function () { socket.emit('message', JSON.stringify({ 'event' : EVENT_TYPE.LOGIN, 'values' : [currentUserNick] })); }); socket.on("disconnect",function(message){ $("#prePage").show(); $("#mainPage").hide(); close(); }); socket.on("message",function(message){ var mData = JSON.parse(message); if (mData && mData.event) { switch (mData.event) { // // user login // case EVENT_TYPE.LOGIN: var user = mData.values[0]; var users = mData.users; if (users && users.length) { var number = users.length; for (var i=0;i<number;i++) { onlineUserMap.put(users[i].uid, users[i]); if (mData.user.uid == users[i].uid && currentUser == null) { currentUser = users[i]; // // listen on private chat // socket.on(currentUser.uid,function(pmessage){ var pmData = JSON.parse(pmessage); if (pmData && pmData.event) { switch (pmData.event) { case EVENT_TYPE.CHAT: var content = pmData.values[0]; appendMessage(formatUserTalkString(pmData.user)); appendMessage("<span> </span>" + content); break; } } }); } } } // // get history message // var data = mData.historyContent; if (data && data.length) { var number = data.length; for ( var i=0;i<number;i++) { appendMessage(formatUserTalkHisString(data[i].user, data[i].time)); appendMessage("<span> </span>" + data[i].content); } appendMessage("<span class='gray'>==================以上为最近的历史消息==================</span>"); } updateOnlineUser(); updateChatWith(); appendMessage(formatUserTalkString(user) + "[进入房间]"); break; // // user logout // case EVENT_TYPE.LOGOUT: var user = mData.values[0]; onlineUserMap.remove(user.uid); updateOnlineUser(); updateChatWith(); appendMessage(formatUserTalkString(user) + "[离开房间]"); break; // // user public chat // case EVENT_TYPE.CHAT: var content = mData.values[0]; appendMessage(formatUserTalkString(mData.user)); appendMessage("<span> </span>" + content); break; case EVENT_TYPE.ERROR: appendMessage("[error state...]"); break; default: break; } } }); socket.on("error",function(){ appendMessage("[server encounts an error...]"); }); socket.on("close",function(){ appendMessage("[server is closed...]"); close(); }); }); //send a message $("#send").click(function(event) { var value = $.trim($("#message").val()); var to = $.trim($("#chatWith").val()); if (value) { $("#message").val(''); var data = JSON.stringify({ 'event' : EVENT_TYPE.CHAT, 'to' : to, 'values' : [value] }); socket.emit('message',data); } }); //logout $("#logout").click(function(event){ var data = JSON.stringify({ 'event' : EVENT_TYPE.LOGOUT, 'values' : [currentUser] }); socket.emit('message',data); $("#prePage").show(); $("#mainPage").hide(); }); });
运行方式sudo node app.js
附:zTool.js如下
(function (exports) { var SimpleMap = exports.SimpleMap = function() { this.map = {}; this.mapSize = 0; }; SimpleMap.prototype.put = function(key, value) { var oldValue = this.map[key]; this.map[key] = value; if (!oldValue) { this.mapSize++; } return (oldValue || value); }; SimpleMap.prototype.get = function(key) { return this.map[key]; }; SimpleMap.prototype.remove = function(key) { var v = this.map[key]; if (v) { delete this.map[key]; this.mapSize--; }; return v; }; SimpleMap.prototype.size = function() { return this.mapSize; }; SimpleMap.prototype.clear = function() { this.map = {}; this.mapSize = 0; }; SimpleMap.prototype.keySet = function() { var theKeySet = []; for (var i in this.map) { theKeySet.push(i); } return theKeySet; }; SimpleMap.prototype.values = function() { var theValue = []; for (var i in this.map) { theValue.push(this.map[i]); } return theValue; }; var CircleList = exports.CircleList = function(maxSize) { this.maxSize = (maxSize || 10); this.list = []; this.index = null; }; CircleList.prototype.clear = function() { this.list = []; this.index = null; }; CircleList.prototype.add = function(value) { if (null == this.index) { this.index = 0; } this.list[this.index++] = value; if (this.index == this.maxSize) { this.index = 0; } }; CircleList.prototype.values = function() { var theValue = []; if (null != this.index) { if (this.list.length == this.maxSize) { for (var i = this.index; i < this.maxSize; i++) { theValue.push(this.list[i]); } } for (var i = 0; i < this.index; i++) { theValue.push(this.list[i]); } } return theValue; }; })( (function(){ if(typeof exports === 'undefined') { window.zTool = {}; return window.zTool; } else { return exports; } })() );
相关推荐
在本课程中,我们将深入探讨 Node.js 的基础,特别是第6天的主题——如何利用 socket.io 实现聊天室功能以及进行文件操作。 一、socket.io 聊天室 Socket.IO 是一个实时应用框架,它允许在客户端和服务器之间进行...
在本项目中,我们主要探讨的是一个基于WebSocket和Socket.IO技术构建的毕业设计——聊天室。这个聊天室的源码包含在"毕业设计聊天室、websocket、socket.io设计源码.zip"压缩包里,其中的核心内容是实现了一个实时...
本项目“react-chat-app”是基于 ReactJS 构建的一个简单聊天应用,它利用了实时通信技术——Socket.io,实现即时消息传递。 **Socket.io 简介** Socket.io 是一个实时应用框架,可以在浏览器和服务器之间提供双向...
这个应用程序借鉴了Grafikart.fr提供的教程——“NodeJS教程 - 创建与NodeJS和Socket.IO的聊天”。在这里,我们将深入探讨Node.js和Socket.IO这两个关键组件,以及它们如何协同工作来构建一个实时聊天系统。 **1. ...
《Marty Socket.IO状态源详解——构建高效实时应用的基础》 在现代Web开发中,实时通信已经成为不可或缺的一部分,WebSocket协议的出现使得双向通信成为可能,而Socket.IO则是在WebSocket之上建立的一个强大的实时...
**JavaScript实时通信技术——Socket.IO** 在Web开发中,实现实时通信是许多应用程序的核心需求,例如在线聊天、协作工具和游戏等。JavaScript作为前端的主要编程语言,提供了多种实现实时通信的技术,其中Socket....
"chatter:socket.io 测试" 这个标题暗示我们正在讨论一个基于Socket.IO的实时通信应用,可能是一个简单的聊天程序。"chatter"通常指的是人们的闲聊,这里可能是项目的名字,表明这是一个用Socket.IO实现的聊天应用的...
**袜子机器人——结合约翰尼五号与socket.io** 在IT行业中,"袜子机器人"(Sockbot)可能是指一种利用Socket.IO库构建的实时通信应用程序。Socket.IO是一款强大的JavaScript库,它允许开发者创建实时、双向的通信...
《深入探讨JavaScript高级II:基于Node.js和Socket.io的聊天应用程序构建》 在现代Web开发中,实时通信已经成为不可或缺的一部分,而Node.js和Socket.io的组合正是实现这一目标的强大工具。本项目“Javascript_...
《使用Socket.IO与Node.js构建实时字谜游戏——lexicontra深度解析》 在现代Web开发中,实时交互成为了一项重要需求,特别是在游戏领域。本文将深入探讨如何利用JavaScript库Socket.IO和Node.js框架来创建一个名为...
6. **IO操作**:Python的IO操作简单直观,支持文件读写、追加、缓冲等功能。例如,`open()`函数用于打开文件,`read()`和`write()`用于读写数据,`close()`用于关闭文件。 7. **数据处理**:Python的数据处理能力...
【标题】"java毕业设计——基于Java的两个通用安全模块的设计与实现.zip"涉及的核心知识点主要围绕Java编程语言,以及在安全领域的应用。这是一份毕业设计项目,旨在通过Java来构建两个通用的安全模块,以增强软件...
【标题】"使用Node.js和Socket.IO构建的HTML5共享画板——DrawingBoard" 在现代Web开发中,实时交互已经成为了一种重要的需求,特别是在协作工具和在线教育领域。`DrawingBoard`项目就是一个很好的示例,它展示了...
它强调了应用的核心技术栈——React负责前端交互,Socket.IO实现双向实时数据传输,以及XP.css用于UI设计,共同创造出一个既现代又具有复古魅力的聊天环境。 **技术知识点详解** 1. **React**:React是由Facebook...
本文将深入探讨如何利用React、Node.js和Socket.io来构建一款类似“DrawSomething”或“DrawMyThingPictionary”的实时在线绘图游戏——“抽奖游戏”。这款游戏的核心特点在于它允许用户实时互动,一边绘制一边猜测...
在本文中,我们将深入探讨如何利用Phaser以及Node.js和Socket.IO来构建一个简单的多人在线游戏——xplo.io。 首先,让我们了解Phaser的核心特性。Phaser提供了丰富的图形渲染能力,支持WebGL和Canvas两种渲染模式,...
第1章 初识 Node.js.ppt 第2章 Javascript基础.ppt 第3章 Node.js基础入门.ppt ...第11章 socket.io 模块.ppt 第12章 MongoDb数据库.ppt 第13章 综合项目——全栈开发博客网.ppt 第14章 课程设计——网络版五子棋.ppt
在Python中,我们可以使用socket模块来实现UDP通信。socket模块提供了创建、配置和操作套接字的功能。首先,我们需要创建一个socket对象,指定其协议类型为SOCK_DGRAM,这代表UDP协议。然后,我们可以绑定IP地址和...
《Node.js与Socket.IO实战:构建实时Web应用——基于“node-socket-dojo”项目》 在现代Web开发中,实时交互已经成为一个重要的需求,而Node.js和Socket.IO的组合正是实现这一目标的强大工具。"node-socket-dojo"是...