爲了複習一下nodeJS, 並且socketIO這東西聽起來就好高端有木有, 並且有人寫過了open, 也能夠做爲本身的參考有木有, 點擊下載源代碼;javascript
express是4.x的版本, 跟之前的配置有些區別, 我才無論呢, 好用就好>﹏<;html
按照正常的流程經過 node install 安裝項目依賴, 項目的依賴以下;java
"dependencies": { "body-parser": "~1.8.4", "cookie-parser": "~1.3.3", "debug": "~2.0.0", "express": "~4.9.8", "jade": "~1.6.0", "morgan": "~1.3.2", "serve-favicon": "~2.1.7", "socket.io": "~1.2.1" }
(若是你像本身建項目的話 直接在命令行下 執行express projectName, express就會爲你自動新建一個項目;)node
先來看下高大上的服務端截圖;web
酷炫的客戶端截圖:chrome
客戶端的主要功能是發送消息, 若是用戶不輸入名字後臺會分配一個名字給客戶端;express
服務端的主要功能是處理用戶發送的數據, 而後把數據保存到json, 同時再把當前的新數據推送到全部 , 有鏈接到當前socket服務器的客戶端;json
簡單的服務端流程以下:數組
//獲取對應的依賴 var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var http = require("http"); //主要就是經過socketIO的實現消息的實時推送; var socketIo = require("socket.io"); //原生fileSystem模塊,把數據保存起來的和獲取數據用的; var fs = require("fs"); .... var app = express(); var server = http.createServer(app); //把socketIO綁定到服務上; io = socketIo( server ); io.on('connection', function (socket) { //socket的各類事件寫在這邊; }) //啓動服務, 監聽的端口設置在3000; server.listen( 3000 , function() { console.log(" server is created "); }); //使用jade模板, 以及設定視圖目錄; app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade');
服務端裏面使用了封裝了一個fs進行簡單的文件操做,包括讀取和寫入的方法, 爲了保存數據用的; 服務器
socket主要的幾個事件要知道,包括:
//這個是socketIO初始化時候的事件; io.on('connection', function (socket) { //客戶端發送 message給服務端的時候的事件, 用戶發送過消息這個會觸發; socket.on('message', function(msg){}); socket.on('disconnect', function (msg) {}); //給當前鏈接的客戶端回傳一條消息; socket.emit("message",{}); //給非當前的全部用戶發送推送消息; socket.broadcast.emit("message",{}); //你能夠給客戶端發送各類事件,名字你找本身起; socket.emit('open',"sb"); socket.emit('hehe',"sb"); socket.emit('cnblogs',"sb"); });
全部的服務端代碼(app.js)
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var http = require("http"); var socketIo = require("socket.io"); var fs = require("fs"); var routes = require('./routes/index'); //var users = require('./routes/users'); var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); // uncomment after placing your favicon in /public //app.use(favicon(__dirname + '/public/favicon.ico')); //app.use('port', process.env.PORT || 3000); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', routes); //app.use('/users', users); // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // development error handler // will print stacktrace if (app.get('env') === 'development') { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); }); }; // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); }); var server = http.createServer(app); /* var server = http.createServer(function(req, res){ res.end("hehe"); }); */ io = socketIo( server ); var clients = {}; var appUtil = require("util")._extend({},{ getRandomId : function() { var i=0; i++; return function() { return "name"+(i++); } }(), read : function( callback ) { /* * data.json保存的數據結構爲 { key:[] Array }; * */ fs.readFile("data/data.json",function(err,data){ data = data.toString(); callback( JSON.parse(data).key ); }); }, write : function( writeData ,callback ) { //讀取數據並重寫數據; this.read(function(data) { //我這個node讀取單個json會返回一個a字符串,我就笑了,什麼狀況 // 若是你直接把json放在數組裏面就沒有這個問題; //data = data[0] === "a" ? data.slice(1) : data; data.push( writeData ); var temp = { key : data }; fs.writeFileSync("data/data.json",JSON.stringify(temp)); callback() }); } }); /* * @desc WebSocket API, 端口3000, msg爲對象: * @param { } 傳遞空對象會返回 {msg : 讀取文件的結果 JSON, name : 隨機的一個name}; * @param { name : "xx" , type : "get" , msg : string }; //msg 讀取文件的結果, type獲取的類型 * @param { name : "xx" , type : "add" , msg : string }; //type 是 add爲 添加, msg是指要添加的消息; */ io.on('connection', function (socket) { socket.emit('open',"laile");//通知客戶端已鏈接 // 這個閉包內的工具方法; var sendMessage = function(name) { appUtil.read(function(data) { //給當前鏈接的用戶發送sock消息 socket.emit("message",{ name : name, msg : data }); //給非當前的全部用戶發送消息; socket.broadcast.emit("message",{ name : name, msg : data }); }); }; socket.on('message', function(msg){ console.log("來消息了"); console.log(msg); //若是是沒有name的,咱們會分配一條name給用戶; var name = msg.name || appUtil.getRandomId(); if(!msg.name) { sendMessage( name ); clients[name] = true; }else if(msg.type == "get") { sendMessage(name); }else if( msg.type == "add" ) { //我勒個去,由於readFile和appendFile是異步的, 因此要添加回調, 固然, 你能夠用同步的readFileSync; appUtil.write({ time : new Date().toString(), "name" : msg.name, "msg" : msg.msg}, function(){ sendMessage(name); }); }; //若是是新用戶的話, 廣播一條叫作新用戶登錄的信息; console.log(name) if(!clients[name]) { clients[name] = true; console.log("廣播新用戶登陸的消息"); //注意 : 這個是socket,不是msg; socket.broadcast.emit("refreshUser",name); }; }); socket.on('disconnect', function (msg) {}); }); server.listen( 3000 , function() { console.log(" server is created "); }); module.exports = app;
客戶端的代碼你要引用socket.io模塊下的socket.io/socket.io.js, 你經過 new WebSocket("ws://127.0.0.1") 一直會提示錯誤, 錯誤消息以下:
WebSocket connection to 'ws://127.0.0.1/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
而後經過socket.io這個庫給咱們提供的方法進行鏈接(我也不知道爲何這個能夠鏈接,使用new WebSocket反正是鏈接不了):
var ws = io.connect('http://localhost:3000');
客戶端的代碼以下:
var ws = null; var name = ""; var Ws = function(url) { /* 只能說呵呵了, 使用new WebSocket沒法鏈接到服務器, 提示握手前斷開鏈接; if(!window.WebSocket) return null; var ws = new WebSocket( 'ws:' + window.location.href.substring(window.location.protocol.length) ); */ var ws = io.connect('http://localhost:3000'); ws.on('open',function(data) { log(data); ws.send({}); }); ws.on("refreshUser", function(msg){ $("<div></div>").html( msg+"登錄了哇" ).appendTo( $("#users") ); }); // socketIo鏈接開始握手的消息在chrome開發工具的請求中能夠看到, // 握手之後的消息傳送沒法截取; ws.on("message", function(data) { $("#output").html(" "); name = data.name; $("#name").val(data.name); var arr = data.msg; while( s = arr.shift() ) { log( s ); }; window.scrollTo(0, 100000); }); var sendMessage = function(msg){ ws.send(msg); }; return ws; function log(s,e) { var output = document.getElementById("output"); var p = document.createElement("p"); p.style.wordWrap = "break-word"; p.style.padding="10px"; p.style.background="#eee"; p.innerHTML = s.name + " at " + (new Date(s.time)).toDateString() + " :<br>==>> <b>"+ s.msg +"</b>"; output.appendChild(p); }; }; function init() { ws = Ws(); if(ws === null) { alert("不支持webSocket!"); }; $("#ipt").keydown(function(e) { var e = e || window.event; if (e.keyCode === 13) { var msg = $(this).val(); if (!msg) return; ws.send({ type : "add", msg : msg, name : $("#name").val() }); $(this).val(''); }; }); }; window.onload = init;
jade這個模板和express的路由什麼的就不說了, 本身寫個兩行就懂了, 教程那麼多, imooc屌炸天是否是哇, 明天覆習JAVASCRIPT搞基程序設計3, 你懂的;
捐給給錢,這個個人支付寶帳號:mayun.taobao.com;