1.Nodejs提供了net模塊給我們,所以我們創(chuàng)建TCP服務(wù)器很簡(jiǎn)單:
1
2
3
4
5
6
7
8
9
10
|
require( 'net' ).createServer( function (socket) { // new connection socket.on( 'data' , function (data) { // got data }); socket.on( 'end' , function (data) { // connection closed }); socket.write( 'Some string' ); }).listen(); |
通過(guò)var server = require('net').createServer();這行代碼我們可以得到tcp服務(wù)器對(duì)象的引用。
server對(duì)象具注冊(cè)了以下幾個(gè)監(jiān)聽(tīng)事件:
listening,connection,close,error
下面一個(gè)例子是在TCP服務(wù)器的聲明周期中監(jiān)聽(tīng)了如上幾個(gè)事件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
var server = require( 'net' ).createServer(); var port = ; server.on( 'listening' , function () { console.log( 'Server is listening on port' , port); }); server.on( 'connection' , function (socket) { console.log( 'Server has a new connection' ); socket.end(); server.close(); }); server.on( 'close' , function () { console.log( 'Server is now closed' ); }); server.on( 'error' , function (err) { console.log( 'Error occurred:' , err.message); }); server.listen(port); |
一旦建立連接成功后,會(huì)得到一個(gè)socket對(duì)象作為回調(diào)中的參數(shù),我們可以操作這個(gè)socket對(duì)象,前面提到過(guò)tcp連接的對(duì)象是可讀可寫的流。作為一個(gè)流對(duì)象,因此能夠監(jiān)聽(tīng)data,end等事件;作為一個(gè)可寫流,具有write()方法。 下面是一個(gè)能夠監(jiān)聽(tīng)用戶輸入的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
var server = require( 'net' ).createServer( function (socket) { console.log( 'new connection' ); socket.setEncoding( 'utf' ); socket.write( "Hello! You can start typing. Type 'quit' to exit.\n" ); socket.on( 'data' , function (data) { console.log( 'got:' , data.toString()) if (data.trim().toLowerCase() === 'quit' ) { socket.write( 'Bye bye!' ); return socket.end(); } //反饋回客戶端 socket.write(data); }); socket.on( 'end' , function () { console.log( 'Client connection ended' ); }); }).listen(); |
因?yàn)閟ocket對(duì)象又是一個(gè)可讀的流,因此你能夠空氣他的pause()和resume(),或者你可以直接使用pipe()方法輸出一個(gè)可寫流:
1
2
3
4
|
var ws = require( 'fs' ).createWriteStream( 'helloworld.txt' ); require( 'net' ).createServer( function (socket) { socket.pipe(ws); }).listen(); |
上面的代碼創(chuàng)建了一個(gè)可寫流對(duì)象,然后將這個(gè)可寫流對(duì)象輸出到客戶端。在客戶端可以得到一個(gè)名為helloworld.txt的文件,
可以用“telnet localhost 4001”來(lái)測(cè)試該例子。
因?yàn)閟ocket對(duì)象同時(shí)具有可讀流的性質(zhì)和可寫流的性質(zhì),因此上面的例子你可以反過(guò)來(lái)形成下面這樣的代碼:
1
2
3
4
|
require( 'net' ).createServer( function (socket) { var rs = require( 'fs' ).createReadStream( 'hello.txt' ); rs.pipe(socket); }).listen(); |
上面的代碼將hello.text文件內(nèi)容輸出到socket對(duì)象中返回給客戶端,當(dāng)內(nèi)容輸出完成后,tcp連接就會(huì)退出,在前面的文章中有說(shuō)過(guò)Pipe的用法,默認(rèn)情況下在數(shù)據(jù)讀取完成后就會(huì)執(zhí)行end方法,因此如果不想要這樣的效果并保持連接的話可以在pipe中添加第二個(gè)參數(shù):{ end : false },并重寫end監(jiān)聽(tīng)。
2.閑置socket 當(dāng)有閑置的socket出現(xiàn)的時(shí)候我們需要進(jìn)行相應(yīng)的清除的工作,由setTimeout方法可以幫我們把閑置的socket對(duì)象關(guān)閉。
1
2
3
4
5
6
|
var timeout = ; // minute socket.setTimeout(timeout); socket.on( 'timeout' , function () { socket.write( 'idle timeout, disconnecting, bye!' ); socket.end(); }); |
下面是一個(gè)更簡(jiǎn)潔的使用方式:
1
2
3
|
socket.setTimeout(60000, function () { socket.end( 'idle timeout, disconnecting, bye!' ); }); |
3.保持連接
socket.setKeepAlive(true);
你也可以添加第二個(gè)參數(shù)在設(shè)置可延時(shí)時(shí)長(zhǎng):
socket.setKeepAlive(true, 10000); // 10 seconds
4.是否使用延時(shí)
kernel會(huì)在發(fā)送tcp數(shù)據(jù)包之前緩存數(shù)據(jù),因此會(huì)占據(jù)一定的延時(shí),這對(duì)于某些小數(shù)據(jù)包場(chǎng)景來(lái)說(shuō)是有用的,但如果你不希望有這樣的延時(shí)的話,那么你可以這樣設(shè)置:
socket.setNoDelay(true);
var port = ;
var host = '...';
server.listen(port, host);
listen方法的第二個(gè)參數(shù)是監(jiān)聽(tīng)客戶端的ip地址,如果填寫則只監(jiān)聽(tīng)所填寫的ip,否則則監(jiān)聽(tīng)所有ip地址,默認(rèn)情況下不填寫。 關(guān)閉服務(wù)器連接,我們可以使用close方法,同時(shí)也可以對(duì)該事件進(jìn)行監(jiān)聽(tīng)。
server.close();
server.on('close', function() {
console.log('server closed!');
});
6.創(chuàng)建一個(gè)簡(jiǎn)單的TCP聊天室服務(wù)器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
var net = require( 'net' ); var server = net.createServer(); var sockets = []; server.on( 'connection' , function (socket) { console.log( 'got a new connection' ); sockets.push(socket); console.log( 'sockets length:' , sockets.length); socket.on( 'data' , function (data) { console.log( 'got data:' , data.toString()); sockets.forEach( function (otherSocket) { if (otherSocket !== socket) { otherSocket.write(data); } }); }); socket.on( 'close' , function () { console.log( 'connection closed' ); var index = sockets.indexOf(socket); sockets.splice(index, ); console.log( 'sockets length:' , sockets.length); }); }); server.on( 'error' , function (err) { console.log( 'Server error:' , err.message); }); server.on( 'close' , function () { console.log( 'Server closed' ); }); server.listen(); |