Nodejs创建TCP服务器
1.Nodejs提供了net模块给我们,所以我们创建TCP服务器很简单:
1 require(‘net‘).createServer(function(socket) { 2 // new connection 3 socket.on(‘data‘, function(data) { 4 // got data 5 }); 6 socket.on(‘end‘, function(data) { 7 // connection closed 8 }); 9 socket.write(‘Some string‘); 10 }).listen(4001);
通过var server = require(‘net‘).createServer();这行代码我们可以得到tcp服务器对象的引用。
server对象具注册了以下几个监听事件:
listening,connection,close,error
下面一个例子是在TCP服务器的声明周期中监听了如上几个事件:
1 var server = require(‘net‘).createServer(); 2 var port = 4001; 3 server.on(‘listening‘, function() { 4 console.log(‘Server is listening on port‘, port); 5 }); 6 server.on(‘connection‘, function(socket) { 7 console.log(‘Server has a new connection‘); 8 socket.end(); 9 server.close(); 10 }); 11 server.on(‘close‘, function() { 12 console.log(‘Server is now closed‘); 13 }); 14 server.on(‘error‘, function(err) { 15 console.log(‘Error occurred:‘, err.message); 16 }); 17 server.listen(port);
一旦建立连接成功后,会得到一个socket对象作为回调中的参数,我们可以操作这个socket对象,前面提到过tcp连接的对象是可读可写的流。作为一个流对象,因此能够监听data,end等事件;作为一个可写流,具有write()方法。
下面是一个能够监听用户输入的例子:
1 var server = require(‘net‘).createServer(function(socket) { 2 console.log(‘new connection‘); 3 socket.setEncoding(‘utf8‘); 4 socket.write("Hello! You can start typing. Type ‘quit‘ to exit.\n"); 5 socket.on(‘data‘, function(data) { 6 console.log(‘got:‘, data.toString()) 7 if (data.trim().toLowerCase() === ‘quit‘) { 8 socket.write(‘Bye bye!‘); 9 return socket.end(); 10 } 11 //反馈回客户端 12 socket.write(data); 13 }); 14 socket.on(‘end‘, function() { 15 console.log(‘Client connection ended‘); 16 }); 17 }).listen(4001);
因为socket对象又是一个可读的流,因此你能够空气他的pause()和resume(),或者你可以直接使用pipe()方法输出一个可写流:
1 var ws = require(‘fs‘).createWriteStream(‘helloworld.txt‘); 2 require(‘net‘).createServer(function(socket) { 3 socket.pipe(ws); 4 }).listen(4001);
上面的代码创建了一个可写流对象,然后将这个可写流对象输出到客户端。在客户端可以得到一个名为helloworld.txt的文件,
可以用“telnet localhost 4001”来测试该例子。
因为socket对象同时具有可读流的性质和可写流的性质,因此上面的例子你可以反过来形成下面这样的代码:
1 require(‘net‘).createServer(function(socket) { 2 var rs = require(‘fs‘).createReadStream(‘hello.txt‘); 3 rs.pipe(socket); 4 }).listen(4001);
上面的代码将hello.text文件内容输出到socket对象中返回给客户端,当内容输出完成后,tcp连接就会退出,在前面的文章中有说过Pipe的用法,默认情况下在数据读取完成后就会执行end方法,因此如果不想要这样的效果并保持连接的话可以在pipe中添加第二个参数:{ end : false },并重写end监听。
2.闲置socket
当有闲置的socket出现的时候我们需要进行相应的清除的工作,由setTimeout方法可以帮我们把闲置的socket对象关闭。
1 var timeout = 60000; // 1 minute 2 socket.setTimeout(timeout); 3 socket.on(‘timeout‘, function() { 4 socket.write(‘idle timeout, disconnecting, bye!‘); 5 socket.end(); 6 });
下面是一个更简洁的使用方式:
1 socket.setTimeout(60000, function() { 2 socket.end(‘idle timeout, disconnecting, bye!‘); 3 });
3.保持连接
socket.setKeepAlive(true);
你也可以添加第二个参数在设置可延时时长:
socket.setKeepAlive(true, 10000); // 10 seconds
4.是否使用延时
kernel会在发送tcp数据包之前缓存数据,因此会占据一定的延时,这对于某些小数据包场景来说是有用的,但如果你不希望有这样的延时的话,那么你可以这样设置:
socket.setNoDelay(true);
5.监听关闭连接
1 var port = 4001; 2 var host = ‘0.0.0.0‘; 3 server.listen(port, host);
listen方法的第二个参数是监听客户端的ip地址,如果填写则只监听所填写的ip,否则则监听所有ip地址,默认情况下不填写。
关闭服务器连接,我们可以使用close方法,同时也可以对该事件进行监听。
1 server.close(); 2 server.on(‘close‘, function() { 3 console.log(‘server closed!‘); 4 });
6.创建一个简单的TCP聊天室服务器
1 var net = require(‘net‘); 2 var server = net.createServer(); 3 var sockets = []; 4 server.on(‘connection‘, function(socket) { 5 console.log(‘got a new connection‘); 6 sockets.push(socket); 7 console.log(‘sockets length:‘, sockets.length); 8 socket.on(‘data‘, function(data) { 9 console.log(‘got data:‘, data.toString()); 10 sockets.forEach(function(otherSocket) { 11 if (otherSocket !== socket) { 12 otherSocket.write(data); 13 } 14 }); 15 }); 16 socket.on(‘close‘, function() { 17 console.log(‘connection closed‘); 18 var index = sockets.indexOf(socket); 19 sockets.splice(index, 1); 20 console.log(‘sockets length:‘, sockets.length); 21 }); 22 }); 23 server.on(‘error‘, function(err) { 24 console.log(‘Server error:‘, err.message); 25 }); 26 server.on(‘close‘, function() { 27 console.log(‘Server closed‘); 28 }); 29 server.listen(4001);