One, use node to build static server
This is the bottom support part of the project. Used to support static resource files such as HTML, CSS, GIF, JPG, PNG, JavaScript, JSON, plain text , and other static resources access. Here is a file map with a MIME type.
Mime.js
/**
* MIME type map
* @ author Cheng liufeng
* @ Date 2014/8/30
* When requesting static server file type HTML, CSS, GIF, jpg, PNG, JA Vascript, JSON, plain text, we will map this file
* *
exports.types = {
"css": "Text/css",
"gif": "Image/gif", c11/> "html": "Text/html",
"ico": "Image/x-icon",
"JPEG": "Image/jpeg",
"jpg": "Image/jpeg",
" JS ":" Text/javascript ","
json ":" Application/json ",
" PDF ":" Application/pdf ",
" png ":" Image/png ",
"svg": "Image/svg+xml",
"swf": "Application/x-shockwave-flash",
"TIFF": "Image/tiff",
"TXT": "Text/plain",
"wav": "Audio/x-wav",
"wma": "Audio/x-ms-wma",
"wmv": "Video/x-ms-wmv",
"xml": " Text/xml "
};
I'll explain the process from the input URL to the page. When the user enters a URL in the browser's address bar.
Next, a series of processes will occur. The first is DNS resolution, which converts the domain name to the corresponding IP address, and then the browser establishes a TCP/IP connection with the remote Web server through TCP three handshake negotiation. The handshake consists of a synchronous message, a synchronous-response message and an answer message, which are passed between the browser and the server. The handshake is first made by the client to attempt to establish the communication, and then the server responds and accepts the client's request, and finally the client issues the message that the request has been accepted. Once the TCP/IP connection is established, the browser sends an HTTP GET request to the remote server through the connection.
The remote server finds the resource and returns the resource using an HTTP response, and the HTTP response state with a value of 200 represents a correct response. At this point, the Web server provides resource services and the client starts downloading resources. The downloaded resources include HTML files, CSS files, javascript files, image files. Then start building a rendering tree and a DOM tree, during which there will be CSS blocking and JS blocking. So the bottom layer is a static server support required. Inside of this I native constructs a static server, does not adopt the express frame.
In fact, the process of each resource file request is a time GET request. Let me explain the service-side process of the client (the browser-side or the curl-by-linux approach). Once a GET request is sent to the server, the server can correspond to the path of a resource file based on a GET request. Knowing this path, we can get the resources under the specified path in a file read-write format and return it to the client.
We know that there are ReadFile and Readfilesync APIs in node files, but the better way is to read the files in a streaming way, and the advantage of streaming is that caching and gzip compression can be used.
OK, so how do I implement caching? Typically, when the client first requests, the server reads the resource file and returns it to the client. But the second time to request the same file, this time still need to send a request to the server. The server will determine whether the resource has been cached based on HTTP header information such as expires, Cache-control, If-modified-since, and so on. If there is a cache, the server side does not access the actual path of the resource file again. Returns the cached resource directly.
Server.js
/** * Chat room service side * Function: implemented the node version of the static server * Implementation of the cache, gzip compression, etc. * @ author Cheng Liufeng * @ Date 2014/8/30//Set port number Var port
= 3000;
Introducing module var http = require (' http ');
var url = require (' URL ');
var fs = require (' FS ');
var path = require (' path ');
var zlib = require (' zlib ');
Introduce file var mime = require ('./mime '). Types;
var config = require ('./config ');
var chatserver = require ('./utils/chat_server ');
var server = Http.createserver (function (req, res) {Res.setheader ("server", "NODE/V8");
Gets the file path var pathName = Url.parse (req.url). PathName; if (Pathname.slice ( -1) = = = "/") {PathName = PathName + "index.html";//default Take the current default index.html}//Security handling (when using Linux Curl command access
, there are security risks) var Realpath = Path.join ("Client", Path.normalize (Pathname.replace (/\.\./g, ""))); Check that the file path exists path.exists (Realpath, function (exists) {//When the file does not exist, output a 404 error if (!exists) {Res.writehead (404, "No
T Found ", {' Content-type ': ' Text/plain '});
Res.write ("The request URL" + PathName + "is not found!"); Res.end ();
else {///when the file exists the processing logic fs.stat (Realpath, function (err, stat) {//Get file extension var ext = path.extname (Realpath); Ext = ext?
Ext.slice (1): "Unknown"; var contentType = Mime[ext] | |
"Text/plain";
Set Content-type res.setheader ("Content-type", ContentType);
var lastmodified = stat.mtime.toUTCString ();
var ifmodifiedsince = "If-modified-since". toLowerCase ();
Res.setheader ("last-modified", lastmodified); if (Ext.match (config).
Expires.filematch)) {var Expires = new Date (); Expires.settime (expires.gettime () + CONFIG.
Expires.maxage * 1000);
Res.setheader ("Expires", expires.toutcstring ()); Res.setheader ("Cache-control", "max-age=" + CONFIG.
Expires.maxage); } if (Req.headers[ifmodifiedsince] && lastmodified = = Req.headers[ifmodifiedsince]) {res.writehead (304, "not
Modified ");
Res.end ();
else {///use stream to read file var raw = Fs.createreadstream (Realpath); var acceptencoding = req.headers[' accept-encoding '] | |
""; var matched = EXt.match (Config.Compress.match);
if (matched && acceptencoding.match (/\bgzip\b/)) {res.writehead ("OK", {' content-encoding ': ' gzip '});
Raw.pipe (Zlib.creategzip ()). pipe (RES); else if (matched && acceptencoding.match (/\bdeflate\b/)) {Res.writehead (ok), {' content-encoding ': ' Def
Late '});
Raw.pipe (Zlib.createdeflate ()). pipe (RES);
else {res.writehead ("OK");
Raw.pipe (RES); }
Below is the normal way to read a file, not recommended
Fs.readfile (Realpath, "binary", function (err, data) {
// if (err) {//// file exists, but have Some error while read
// Res.writehead ({' Content-type ': ' Text/plain '}); res.end (err); else {//// file exists, can success return
// Res.writehead (= ' Content-type ': ContentType}); res.write (data, "binary"); res.end ();
// }
// });
}
});
}
});
});
Listening on Port 3000.
Server.listen (port, function () {
Console.log ("Server is listening on port" + Port + "!");
});
Let the Socket.io server and the HTTP server share a port
Chatserver.listen (server);
Second, the service side uses the WebSocket to construct the chat room service end
Why use WebSocket?
We know that the current mainstream chat room is still using AJAX to achieve client and server communication. A polling mechanism is used. The so-called polling, that is, the client every once in a while to send a request, ask the service side, see the server has no new chat data, if there is new data, return to the client.
WebSocket is completely different. WebSocket is based on long links. Is that once the client and server have established the link, the link will always exist. is a Full-duplex communication. This time the mechanism is somewhat similar to the publish-subscribe model. The client subscribes to events and pushes them to the client once a new data appears on the server.
WebSocket uses the WS protocol, not the HTTP protocol or HTTPS protocol. Another advantage of adopting websocket is that it can reduce a lot of data traffic. The beginning of the article, I have introduced a traditional resource request process, need three times handshake protocol, and each request header occupies a larger space, this will be very cost traffic. The header in the WebSocket is very small-about 2 Bytes.
/** * Chat Service.
* * var socketio = require (' Socket.io ');
var io; var guestnumber = 1; Initial username number var nicknames = {}; Nickname list var namesused = []; Used username var currentroom = {};
Current chat room function assignguestname (socket, Guestnumber, nicknames, namesused) {var name = ' Guest ' + guestnumber;
Nicknames[socket.id] = name;
Socket.emit (' Nameresult ', {success:true, name:name});
Namesused.push (name);
return guestnumber + 1;
function joinroom (socket, room) {socket.join (room);
Currentroom[socket.id] = room;
Socket.emit (' Joinresult ', {room:room});
Socket.broadcast.to (room). Emit (' message ', {text:nicknames[socket.id] + ' has joined ' + room + '. '
}); function handlemessagebroadcasting (socket) {socket.on (' message ', function (message) {socket.broadcast.to (
Message.room). Emit (' message ', {text:nicknames[socket.id] + ': ' + message.text});
});
} Exports.listen = function (server) {IO = Socketio.listen (server);
Io.set (' Log level ', 1); Define connection processing for each user Io.sockets.on ('Connection ', function (socket) {//assign a username Guestnumber = assignguestname (socket, Guestnumber, nicknames, namesused);
Add users to the chat room Lobby joinroom (socket, ' Lobby ');
Processing chat information handlemessagebroadcasting (socket, nicknames);
Handlenamechangeattempts (socket, nicknames, namesused);
Handleroomjoining (socket);
Handleclientdisconnection (socket, nicknames, namesused);
}); };
Third, use angular to build chat room client
Why use angular?
As a front-end MVC framework, Angular.js is undoubtedly compelling. Modular, bidirectional data binding, instruction system, dependency injection. and angular built-in jquerylite, which makes it easy for students who are familiar with jquery syntax.
Of course, personally, angular has a great advantage in building a single page application and Crud project. Our chat room is based on the purpose of SPA (single page application).
Index.html
How do I build a single page application? The principle of single page application?
Let's talk about the principle of single page application. The so-called single page, not the entire page without refreshing. When you review Google Chrome's console console, you'll find that Ajax is used to request resources asynchronously within the angular. So just partial refresh. But this approach has made a lot of progress relative to the previous DOM node deletions and modifications.
To build a single page application, we need to use angular-route.js. This angular can help us define routing and corresponding logical processing controllers. With it, we can implement a single page application.
App.js
/**
* Client (currently only supports browsers, will be extended to mobile end) program Entry file
* Create a module, and named Chatapp
* Configure routing, implement Single-page application (single page application)
* *
var Chatapp = angular.module ("Chatapp", [' Ngroute ']);
Routing configuration
chatapp.config (function ($routeProvider) {
$routeProvider. When ('/', {
templateurl: ' views/ Init.html ',
controller: ' Initctrl '
})
. When ('/init ', {
templateurl: ' views/init.html ',
Controller: ' Initctrl '
});
The code logic for the client chat interface is as follows
Initctrl.js
/**
* Initctrl/
angular.module (' Chatapp '). Controller (' Initctrl ', function ($scope) {
var socket = Io.connect (' http://127.0.0.1:3000 ');
Socket.on (' Nameresult ', function (result) {
var message;
if (result.success) {Message
= ' Your are now known as ' + Result.name + '. ';
Console.log (' message= ', message);
document.getElementById (' Guestname '). InnerHTML = message;
else {message
= Result.message;
}
});
Socket.on (' Joinresult ', function (result) {
document.getElementById (' Room '). InnerHTML = Result.room;
});
$scope. SendMessage = function () {
var message = {
room: ' Lobby ',
text:document.getElementById (' User_ Input '). Value
};
Socket.emit (' message ', message);
Socket.on (' message ', function (message) {
var p = document.createelement (' P ');
p.innerhtml = Message.Text;
document.getElementById (' message '). appendchild (P);
});
Multi-people chat rooms based on node.js and Socket.io
Just learn node.js, want to do something to practice practicing. Online things are more and more miscellaneous, took a lot of detours, spent a day on the tune code. Refer to an article on the web, rewrite some of the code, the original is based on the node-websocket-server framework, I do not use the framework, simply Socket.io.
First, the basic function
1, users can enter a nickname at random to login
2, after the successful login
1 for the users who are logged in, list all the online users, listing the latest history chat record
2 for Logged-in users, notify new users to enter the room, update the online user list
3. Exit Login
1) Support for direct exit
2 When a user exits, all other online users will receive information, notify the user to exit the room, and update the online user list
4, Chat
1 Chat is broadcast, broadcast information to all users connected to the online
5. Some error handling
1) briefly handle the system logic errors, network errors and other special circumstances of the error tips
Problem: The function is not perfect, there is a bug (after exiting, the new user login again, or the original user). Time to perfect.
Second, Technical introduction
Socket.io (official website: http://socket.io/) is a cross-platform, a variety of connection ways to automatically switch, do instant messaging development is very convenient, and EXPRESSJS provides a good combination of traditional request, that can be in the same domain name, The same port provides two ways to connect: Request/response, WebSocket (Flashsocket,ajax ...).
This article gives a detailed introduction to the use of Socket.io: http://www.jb51.net/article/71361.htm
"Use Node.js and WebSocket to be a multiplayer chat room," http://www.html5china.com/HTML5features/WebSocket/20111206_3096.html
III. Matters of note
(1) The client references Socket.io.js:
<script src= "/socket.io/socket.io.js" ></script>
may fail to load (I've spent a lot of time here)
Can be changed to:
<script src= "Http://ip:port/socket.io/socket.io.js" ></script>
(The IP address and port number of the corresponding server, such as localhost and port 80)
(2) When the implementation of the broadcast, reference to the official website of the wording, unexpectedly does not work, such as:
var io = require (' Socket.io '). Listen
Io.sockets.on (' Connection ', function (socket) {
socket.broadcast.emit (' User connected ');
Socket.broadcast.json.send ({A: ' message '});
};
And then I read this: Http://stackoverflow.com/questions/7352164/update-all-clients-using-socket-io.
The following is the only effect:
Io.sockets.emit (' Users_count ', clients);
Four, the effect chart
V, source download
Nodejs Chat Room (click here to download the source)
Ps:
1, run at the command line
Then open index.htmlin the browser, and if the browser (FF, Chrome) does not support it, upgrade to a version that supports WebSocket.
2, recommended Node.js IDE Webstorm
The above content is based on angular and nodejs to build chat rooms and multiplayer chat room implementation, I hope you like.