在这个例子中,其实node.js并没有真正起到服务器的作用,因为我们这里可以直接运行client.html文件,而不用输入url请求,当然,要想输入url请求页面内容还需要加入请求静态文件的代码。这个实例中node.js最重要的作用就是将服务端迁移到了js,实现了客户端和服务端语言上的统一,我们只要在浏览器上同时运行两个client.html客户端页面,即可进行简单的即是通讯了,socket.io才是我们真正用来实现即时通讯的消息的收发。
var server = http.createServer(callback);//开启http服务
var io = require("socket.io").listen(server);//socketio来监听http服务器
接下来直接上客户端代码client.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>socketIO - Simple chat</title> <script src="./socketio.js"></script> <style> * { font-family:tahoma; font-size:12px; padding:0px; margin:0px; } p { line-height:18px; } div { } .textInput{width:500px;margin: 0 auto;margin-top: 50px;} #content { padding:5px; background:#ddd; border-radius:5px; overflow-y: scroll; border:1px solid #CCC; height: 160px;width: 400px;float: left;} #input { border-radius:2px; border:1px solid #ccc; margin-top:10px; padding:5px; width:400px; } #status { width:88px; display:block; float:left; margin-top:15px; } .onlineList { width: 200px; height: 160px; background-color: #ccc; border: 1px solid #DDD; margin-top: 50px; margin-left: 420px; } li { display: inline;border: 1px solid red; } .ul { margin-left:auto; margin-right:auto; width: 600px; } </style> </head> <script type="text/javascript"> //window.onbeforeunload = disConnect; </script> <body> <div class="ul"> <div id="content"></div> <div class="onlineList"> 当前在线: <div id="list"> </div> </div> </div> <div class="textInput"> <span id="status">connecting</span> <input type="text" id="input" value="只能选择右上列表上的姓名进行登录"/> </div> <script src="./jquery.js"></script> <script src="./client.js"></script> </body> </html>
"use strict"; // for better performance - to avoid searching in DOM var content = $('#content'); var input = $('#input'); var statusObj = $('#status'); var userList = $("#list"); // my color assigned by the server var myColor = false; // my name sent to the server var myName = false; var connection = null; var currentToUser = null; connect(); window.onbeforeunload = beforeDisConnect;//监听浏览器关闭前的事件 window.onunload = disConnect;//监听浏览器关闭时 /** * Send mesage when user presses Enter key */ input.keydown(function (e) { if (e.keyCode === 13) { var msg = $(this).val(); if (!msg) { return; } if (!myName) { myName = msg;//定义名字 statusObj.text(myName); input.val(""); if (connection) { connection.json.send({ logicId: "login", username: myName }); } return; } var time = new Date(); var tmpTime = time.getFullYear() + "-" + ((time.getMonth() < 9 ? "0" : "") + (time.getMonth() + 1)) + "-" + ((time.getDate() < 10 ? "0" : "") + time.getDate()) + " " + ((time.getHours() < 10 ? "0" : "") + time.getHours()) + ":" + ((time.getMinutes() < 10 ? "0" : "") + time.getMinutes()) + ":" + ((time.getSeconds() < 10 ? "0" : "") + time.getSeconds()); // send the message as an ordinary text msg = { "@class": "test.EntityIn", logicId: "chat", username: myName, msg: input.val(), to:currentToUser,time:tmpTime}; //alert(typeof(object)); connection.json.send(msg); $(this).val(''); // disable the input field to make the user wait until server // sends back response } }); /** * Add message to the chat window */ function addMessage(author, message, dt) { content.prepend('<p><span>' + author + '</span> @ '+dt+ ': ' + message + '</p>'); } function connect() { // open connection connection = io.connect('http://127.0.0.1:1337', { 'reconnect': false }); connection.on('connect', function (data) { // first we want users to enter their names input.removeAttr('disabled'); statusObj.text('登录:'); connection.send(1); }); connection.on("error", function (error) { // just in there were some problems with conenction... content.html($('<p>', { text: 'Sorry, but there\'s some problem with your ' + 'connection or the server is down.' })); }); // most important part - incoming messages connection.on("message", function (message) { var logicId = message.logicId; if (logicId == 'conn_success') {//连接成功 var users = message.users; for (var i = 0; i < users.length; i++) { userList.append('<a href="#" onclick="chatToSb(this.innerHTML)">'+users[i]+'</a></br>'); } } else if (logicId == "chat") { addMessage(message.from,message.msg,message.time); }else if(logicId == "history"){ var historyMsgs = message.historyMsgs; for(var i = 0; i < historyMsgs.length; i++){ addMessage(historyMsgs[i].from,historyMsgs[i].msg,historyMsgs[i].time); } } }); } function chatToSb(username) { currentToUser = username; } function disConnect(){ connection.disconnect(); //alert("断开连接"); } function beforeDisConnect() { return "确认离开"; }
"use strict"; var http = require('http'); /** * Global variables */ var history = []; // list of currently connected clients (users) var users = ["user1","user2"]; var clients = []; /** * HTTP server */ var server = http.createServer(function (request, response) { // Not important for us. We're writing socket.io server, not HTTP server }); server.listen(1337); /** * socketio server */ var io = require("socket.io").listen(server); //io监听socket事件 io.on('connection', function (connection) { console.log((new Date()) + ' Connection from origin ' + connection.id + '.'); var json = { logicId:"conn_success",users: users }; connection.json.send(json); var userName = false; console.log((new Date()) + ' Connection accepted.'); connection.on('message', function (message) { console.log(message); if (message.logicId == "login") { clients[message.username] = connection; //将用户名与连接对应 connection.username = message.username; }else if(message.logicId == "chat") {//用户发起会话 //1、查找该用户是否有历史消息 var toUser = message.to;//会话目标 var from = message.username;//会话发起人 if(history[toUser]&&history[toUser][from]){ var historyMsgs = []; for (var i = 0; i < history[toUser][from].length; i++) { historyMsgs.push(history[toUser][from][i]); }; connection.json.send({logicId:"history",historyMsgs:historyMsgs}); } //2、检查目标用户是否在线,若在线,转发用户请求,否则,存为历史会话中 var objConnect = clients[toUser]; var chatJson = {logicId:"chat", from: from, time: message.time, msg: message.msg }; connection.json.send(chatJson); if (objConnect) { objConnect.json.send(chatJson); } else {//存储于历史会话中 if (!history[from]||!history[from][toUser]) { if (!history[from]) { history[from] = []; } history[from][toUser] = []; } history[from][toUser].push(chatJson); } } }); // user disconnected connection.on('disconnect', function (socket) { console.log("关闭连接:" + socket); delete clients[connection.username];//删除用户的连接 }); });
这里都假设大家是在win7的环境下,并且装了node.js,方便调试的话还可以安装node-inspector调试工具,或者用webStorm IDE,具体的可以参看我的前一篇博文,除了这三个文件当然还需要服务端和客户端的socket.io文件,node.js就是下载第三方包的方式了,客户端的socket.io文件网上可以找到的。
接下来简单介绍一下以上代码实现的功能以及用法,打开页面后首先就是登录,由于例子比较简单,并没有单独的登录页面,直接在文本框中输入用户名,注意(这里的用户名只能是user1或者user2,读者可以在server.js的users添加自己需要的用户名,这里其实是固定的),然后回车,就是登录了,然后输入需要发送的信息,并且点击接受者的用户名,否则会接收者是空的,关闭页面的时候,我们会监听页面关闭事件,给服务端发送disconnect事件,删除当前用户名的连接。根据这个流程,代码其实很简单,就不再详解了。
本来不喜欢贴源代码的,但是鉴于给大家一个实际的效果,就贴出来了,做一个参考,希望能帮到大家,也请大牛赐教。