互聯網的運做,最根本的驅動就是信息的交互,NodeJS 在數據交互這一塊作的很帶感,異步編程讓人很愜意,關於 NodeJS 的數據通訊,最基礎的兩個模塊是 NET 和 HTTP,前者是基於 TCP 的封裝,後者本質仍是 TCP 層,只不過作了比較多的數據封裝,咱們視之爲更高層。html
本文先述說 NodeJS 的 NET 模塊工做機制,下次再談一談 HTTP 模塊。node
NodeJS 底層支撐是 v8,v8 是用 C++ 編寫的一個編譯和運行 JavaScript 代碼的庫,說到 TCP/UDP,寫 C/C++ 的童鞋確定不會感到陌生,在創建 socket 鏈接的時候,基本都會涉及到相關的知識。編程
這裏先解釋下服務器端和客戶端之間的一些共性和差別。關於數據交互,咱們能夠想象成,Server 與 Client 之間創建了一個管道(pipe),這個管道有兩個分支,一個是用於發送 S 到 C 的數據,一個是用於發送 C 到 S 的數據。那麼這個管道是如何創建的呢?windows
首先,Server 監聽本地的某個端口(所謂端口,能夠理解成對外交流的攤鋪),Client 很明確本身要跟誰去交流,他去訪問 Server 的那個攤鋪,因而二者之間就能夠溝通了。因此 Server 跟 Client 之間的差別是十分明顯的,Server 會監聽端口,而 Client 去訪問端口。api
Unix/Linux 系統跟 windows 有些不一樣,他能夠去監聽端口,也能夠去監聽文件,也就是說他能夠把端口和文件都當作對外交流的攤鋪。那麼 Client 能夠經過訪問一個文件與 Server 創建起 pipe。服務器
在電腦上安裝好了 Node 以後,咱們就能夠引用 Node 提供的模塊,Node 內置了不少模塊,如文件處理(FireSystem)、控制檯(Console)、數據流(Stream)等等,這些我會在之後的文章中提到。創建 TCP 鏈接須要用到的是 Node 的 NET 模塊。使用一個模塊十分簡單:dom
var net = require('net');
net
是一個系統模塊,也就是安裝 Node 以後自帶的模塊,不必對他感到畏懼,其實他的內部也是十分簡單的:異步
var Net = function(){}; Net.methodA = function (){}; Net.methodB = function (){}; module.exports = Net;
咱們能夠簡單理解 net 模塊的內部實現,他就是一個 Net 類,上面綁定了不少的 methods,require 以後,至關於返回一個 Net 類,此時咱們就能夠盡情使用 Net 中定義的全部方法和屬性了。socket
Node 中開啓一個 TCP 服務器:異步編程
// server.js var net = require('net'); var server = net.createServer(function(socket) { //'connection' listener console.log('server connected'); socket.on('end', function() { console.log('server disconnected'); }); socket.on('data', function(){ socket.end('hello\r\n'); }); }); server.listen(8124, function() { //'listening' listener console.log('server bound'); });
上面這段代碼應該很好理解,首先 net.createServer
建立一個 TCP 服務,這個服務綁定(server.listen)在 8124 這個端口上,建立 Server 後咱們看到有一個回調函數,這個回調函數的實現方式是怎麼樣的呢?
net.createServer = function(callback){ // 每次客戶端鏈接都會新建一個 socket var socket = new Socket(); callback && callback(socket); };
在調用上面函數的時候傳入一個參數,這個參數也是函數,而且接受了 socket ,這個由其餘方法構造的一個管道(pipe),他的做用就是用來數據交互的。第一節中咱們說到了,pipe 是須要 Client 跟 Server 打招呼才能創建的,若是此刻沒有客戶端訪問 Server,這個 socket 就不會存在了。
既然 Socket ,也就是管道(pipe)尚未存在,那確定是不會存在通信的,下面來寫一個客戶端程序:
// client.js var net = require("net"); var client = net.connect({port: 8124}, function(){ console.log('client connected'); client.write('world!\r\n'); }); client.on('data', function(data) { console.log(data.toString()); client.end(); }); client.on('end', function() { console.log('client disconnected'); });
net.connect
顧名思義,就是鏈接到服務端,第一個參數是對象,設置端口(port)爲 8124,也就是咱們服務器監聽的端口,因爲沒有設置 host 參數,那默認就是 localhost (本地)。在 Server 中,socket 是管道的一端,而在 client 中,client 自己就是管道的一端,若是是多個客戶端鏈接 Server,Server 會新建多個 socket,每一個 socket 對應一個 client。
數據的通訊就十分簡單了,首先運行服務器程序:
node server.js
此時便會有一個服務器監聽 8124 端口,而後打開一個客戶端程序:
node client.js
那麼二者之間的信息交互就開始了。具體他們是怎麼交流的呢?
首先咱們要說一說 NodeJS 的 EventEmitter 模塊。這個模塊就是一個事件中心,以前寫過相關的內容,能夠看看簡介版的 EventEmitter,戳我。EventEmitter 也就是如此,能夠 on 添加事件到事件池,也能夠 trigger 觸發事件,固然能夠從事件池中刪除事件 off。
NET 模塊是繼承 EventEmitter 的,因此他建立的不少對象能夠:
client.on('data', function(data) { console.log(data.toString()); client.end(); });
如上綁定不少自定義的事件,等到交互中須要信息交流的時候再觸發。就拿上面這句代碼來講,client 綁定了一個 data 事件,這個事件會在 Server 有信息傳過來的時候觸發,他所作的工做,先打印傳過來的數據,而後 end() 關閉這個管道(pipe)。
JavaScript 是基於事件的一門語言,幾乎全部的動做都是由事件驅動的,這個在異步編程中顯得十分突出。
Server 除了有 listen 函數外,還有不少的接口:
Server.close([callback])
,中止監聽,那麼以前的全部管道也就沒有用了。Server.maxConnections
,Server 的最大鏈接數,這個鏈接數是有上限的(跟系統有關),咱們也能夠本身設定鏈接數的最大上限(不超過系統最大鏈接數)。
Server.address()
,在 listen 以後能夠經過這個函數拿到服務器的相關信息。
// grab a random port. server.listen(function() { address = server.address(); console.log("opened server on %j", address); });
還有 write、end、destroy、pause、resume 等等不少豐富的接口,能夠在這裏查看詳情http://nodejs.org/api/net.html。
轉 http://www.cnblogs.com/hustskyking/p/nodejs-net-module.html