モジュールシンプル設計——sockete.ioチャットコード
16257 ワード
インターネット上の各種教程とコードを参照して、簡単なオンラインチャットを実現し、指向性の発信をサポートします。
サーバ端
app.js(expressを使ってスタティックサービスを構築し、socket.ioでサーバー側のモニターを設立する)
添付:zTool.jsは以下の通りです。
サーバ端
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>
<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 ap.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;
}
})() );