1. 程式人生 > >Node.js開發入門—UDP程式設計

Node.js開發入門—UDP程式設計

Node.js也提供了UDP程式設計的能力,相關類庫在“dgram”模組裡。

與TCP不同,UDP是無連線的,不保障資料的可靠性,不過它的程式設計更為簡單,有時候我們也需要它。比如做APP的統計或者日誌或者流媒體,很多流媒體協議都會用到UDP,網上一搜一大堆。

使用UDP,如果你要傳送資料,只需要知道對方的主機名(地址)和埠號,扔一訊息過去即可。至於對方收不收得到,聽天由命了。這就是資料報服務,類似快遞或郵件。

我們這次來介紹一下Node.js裡的UDP程式設計,我會提供一個UDP版本的echoServer和echoClient。

UDP程式設計的一般模型

客戶端和服務端分開來說。

先說服務端吧。

服務端

作為UDP伺服器,要想接收來自客戶端的訊息,在Node.js裡,大體有這麼幾步:

  1. 匯入dgram模組
  2. 建立socket(套接字)
  3. 處理message事件
  4. 繫結埠

後面我們的echoServer示例可以看到具體的程式碼。

客戶端

客戶端UDP程式設計就更簡單了,一下幾步,就可以了:

  1. 匯入dgram模組
  2. 建立socket(套接字)
  3. 傳送訊息

當然有時你也可能希望客戶端也能收到服務訊息,比如你發一個訊息給服務端,希望服務端反饋,那此時就也需要處理message事件和繫結埠。具體就看我們的echoClient示例了。

API介紹

要使用dgram模組,只需這樣:

var dgram = require('dgram');

引入了dgram後,就可以使用它提供的方法createSocket來建立套接字了。createSocket方法返回一個dgram.Socket物件,這個物件提供了一系列的方法和事件。

dgram.Socket的bind方法把socket和一個埠繫結到一起,比如echo服務的埠是7,那下面的程式碼片段就建立了一個socket並繫結到埠7上:

var dgram = require('dgram');
var serverSocket = dgram.createSocket('udp4');
serverSocket.bind(7);

在有訊息到達時dgram.Socket會發射message事件,我們監聽這個事件就可以處理訊息:

serverSocket.on('message', function(msg, rinfo){
  ...
});

message事件對應的回撥函式有兩個引數,一個是Buffer物件msg,代表客戶端傳送過來的資料。一個是rinfo,攜帶了遠端主機的資訊,rinfo.address是遠端主機的地址,rinfo.port是遠端主機的埠。

dgram.Socket還有“error”、“close”、“listening”等事件,參考線上文件:https://nodejs.org/api/dgram.html

要傳送資料,可以呼叫dgram.send方法,就像下面這樣:

var msg = new Buffer('Hello Server');
serverSocket.send(msg, 0, msg.length, 7, "127.0.0.1");

示例

echoServerUdp.js實現了我們的echoServer示例,程式碼如下:

var dgram = require('dgram');

var serverSocket = dgram.createSocket('udp4');

serverSocket.on('message', function(msg, rinfo){
  console.log('recv %s(%d bytes) from client %s:%d\n', msg, msg.length, rinfo.address, rinfo.port);

  //echo to client
  serverSocket.send(msg, 0, msg.length, rinfo.port, rinfo.address);
});

//    err - Error object, https://nodejs.org/api/errors.html
serverSocket.on('error', function(err){
  console.log('error, msg - %s, stack - %s\n', err.message, err.stack);
});

serverSocket.on('listening', function(){
  console.log("echo server is listening on port 7.");
})

serverSocket.bind(7);

echoClientUdp.js實現了echo客戶端,程式碼如下:

var dgram = require('dgram');

var clientSocket = dgram.createSocket('udp4');

var messages = [
  'Hello, Echo Server.',
  'Are you OK?',
  'I am happy.',
  'A little panda found a pumpkin.'
];

var index = 0;

function sendMsg(){//send to server
  var msg = messages[index];
  index = index + 1;
  if(index == messages.length){
    index = 0;
  }
  clientSocket.send(msg, 0, msg.length, 7, "localhost");
}

//start a timer to send message to echoServer
setInterval(sendMsg, 1000);

clientSocket.on('message', function(msg, rinfo){
  console.log('recv %s(%d) from server\n', msg, msg.length);
});

clientSocket.on('error', function(err){
  console.log('error, msg - %s, stack - %s\n', err.message, err.stack);
});

clientSocket.bind(54321);

看起來客戶端比服務端還要複雜一些,這是因為作為echo客戶端,我需要顯示服務端傳送的訊息,所以,也需要監聽到一個埠(在示例中是54321)。另外,我還要不斷髮送資料給服務端,所以用setInterval啟動了一個週期性定時器,迴圈傳送一個字串陣列內的訊息。

setInterval是Node.js的global物件提供的方法,用來啟動一個週期性定時器,原型如下:

setInterval(cb, ms)

第一個引數是定時器觸發時會執行的回撥函式,第二個引數是定時器的週期,單位是毫秒。我們的示例中,每隔1000毫秒傳送一條訊息給伺服器。

setInterval返回一個代表定時器的值,你可以把它傳遞給clearInterval來取消對應的定時器。

另外echoServer和echoClient在處理dgram.Socket的error事件時,用到了Error物件,文件在這裡:https://nodejs.org/api/errors.html

好啦,程式碼就這樣,可以開啟兩個命令列視窗,分別執行“node echoServerUdp.js”和“node echoClientUdp.js”來觀察效果。

其它文章: