构建TCP服务器
Node以http.Server伪类的形式实现HTTP服务器,该伪类继承自.net Server中的TCP服务器伪类。
TCP服务器声明周期
var server = require('net').createServer();
var port = 4001;
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.write('hello welcome');
socket.end();
server.close();
});
server.on('close',function(){
console.log('server is closed');
});
server.on('error',function(){
console.log('error occured:',err.message);
});
server.listen(port);
可用管道将套接字写入可写流中:或者向套接字输入
var ws = require('fs').createWriteStream('myfile.txt');
require('net').createServer(function(socket){
socket.pipe(ws);
}).listen(4001);
require('net').createServer(function(socket){
var rs = require('rs').createReadStream('hello.txt');
rs.pipe(socket);
}).listen(4001);
设置超时时间:
socket.setTimeout(60000,function(){
socket.end('idle timeout,disconnecting bye!');
});
//设置两个终端之间的连接处于运行状态(通过发送带有ACK标志的空TCP包触发另一端的空应答来实现)
socket.setKeepAlive(true);
//指定最后接收到的包与下一个保持运行包之间的延迟时间
socket.setKeepAlive(true,10000);//10s
在发送TCP数据包之前,内核会缓冲数据。但它会导致延迟发送数据。如果要在write命令之后强制数据立即被发送出去:
socket.setNoDelay(true);//默认为false.
监听连接:
socket.listen(port,host);//如果没有传host,则接收任意ip地址的连接
构建完整的TCP聊天服务器
var server = require('net').createServer();
var sockets = [];
var port = 4001;
server.on('listening',function(){
console.log('server is listening on port',port);
});
server.on('connection',function(socket){
console.log('server has a new connection');
sockets.push(socket);
socket.on('data',function(data){
console.log('got data:',data);
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,1);
});
});
server.on('close',function(){
console.log('server is closed');
});
server.on('error',function(){
console.log('error occured:',err.message);
});
server.listen(port);
构建HTTP服务器
require('http').createServer(function(req,res){
res.writeHead(200,{'Content-Type':'text/plain'});
res.end('hello world');
}).listen(4000);
在监听request事件时,回调函数会得到一个http.ServerRequest对象作为第一个参数,这个对象包含以下属性:
req.url:一个字符串形式的请求url.(不包括模式,主机名或者端口)
req.method:请求的方法,GET,POST,DELETE或者HEAD
req.headers:此对象拥有请求上所有的HTTP头。
第二个参数为http.ServerResponse对象。为了写入响应头,可以使用res.writeHead(status,headers)函数。headers是可选的。
res.writeHead(200,{
'Content-Type':'text/plain',
'Cache-Control':'max-age=3600'
});
//设置响应头
res.setHeader(name,value);
//删除响应头
res.removeHeader(headName);
//写入响应主体
res.write(string or buffer);
以流的形式传送HTTP分块响应
HTTP分块编码允许服务器持续向客户端发送数据,而不需要发送数据大小,即他不会发送Content-Length响应头,而是:Transfer-Encoding:chunked.此响应头可以让客户端接收若干块数据作为响应主体,并在客户端结束响应之前发送一个具有0长度的结束块。
传送文件:
require('http').createServer(function(req,res){
res.writeHead(200,{'Content-Type':'video/mp4'});
var rs = require('fs').createReadStream('test.mp4');
rs.pipe(res);
}).listen(4000);
关闭服务器:server.close();
静态文件上传服务器:
var path = require('path'),
fs = require('fs');
require('http').createServer(function(req,res){
var file = path.normalize('.'+req.url);
console.log('trying to serve',file);
function reportError(err){
console.log(err);
res.writeHead(500);
res.end('Internal server error');
}
fs.exists(file,function(exists){
if(exists){
fs.stat(file,function(err,stat){
var rs;
if(err){
return reportError(err);
}
if(stat.isDirectory()){
res.writeHead(403);res.end('forbidden');
}else{
rs = fs.createReadStream(file);
rs.on('error',reportError);
res.writeHead(200);
rs.pipe(res);
}
});
}else{
res.writeHead(404);
res.end('not found');
}
});
}).listen(4000);
构建TCP客户端
连接服务器:
var net = require('net');
var port = 4000;
var host = localhost;
//不传host则默认为localhost.callback为连接建立后的回调函数
var conn = net.createConnection(port,host,callback);
conn.write('here is a string');
conn.write('SGVsbG8gV29ybGQH','base64');
conn.write(new Buffer('hello world'));
//可传递一个回调函数
conn.write('hey',function(){console.log('data written');})
//监听data事件接收来自服务器的数据
conn.on('data',function(data){
console.log('some data has arrived',data);
})
//设置编码格式
conn.setEncoding('base64');
//终止连接
conn.end();
//conn.end('bye bye','utf-8');
//处理错误
conn.on('error',function(err){
console.error('this error:'+error.message+',code:'+error.code);
});
创建HTTP请求
创建get请求
var http = require('http');
var options = {
host:"www.google.com",
port:80,
path:'/index.html'
};
http.get(options,function(res){
console.log('got response:'+res.statusCode);
})
http.request函数会返回一个http.ClientRequest对象。使用它可以发送数据:
var options = {
host:"www.google.com",
port:80,
path:'/index.html',
method:"POST",
headers:{
"Accept":"text/json",
"IF-Modified-Since":"Sat,28 Jan 2012 00:00:52 GMT"
}
}
var request = http.request(options,function(response){
console.log('STATUS:',response.statusCode);
console.log('HEADERS::',response.headers);
response.setEncoding('utf8');
response.on('data',function(chunk){
console.log('body:',chunk);
});
});
request.write('this is a piece of data');
request.end();//要调用end()函数不然无法触发response事件
当HTTP服务器的响应返回时就会触发response事件,但是并没有响应主体,可以在response上注册“data”事件得到响应主体。
使用HTTP.Agent维护套接字池
在创建HTTP请求时,Node在内部使用了一个代理。他负责维护一个活动套接字池,对指定的主机名和端口对,套接字池包含已经被打开但是未使用的连接。请求结束时,套接字会发射close事件或者agentRemove事件从代理的套接字池被删除。如果想让HTP请求打开一段较长时间,可以将其从套接字池中删除。
req.on('socket',function(socket){
socket.emit('agentRemove');
});
Node允许在一个给定的线程上的每个主机-端口最多有5个打开连接的套接字。可以通过option对象传递agent:false来使代理的套接字池失效:
var options = {
host:"www.google.com",
port:80,
path:'/index.html',
method:"POST",
agent:false
}
//或者通过修改http.Agent.defaultMaxSockets来改变允许的最大数目.这个修改是全局性的。
http.Agent.defaultMaxSockets = 10;
创建请求时也可以指定HTTP代理。
var agentOptions = {
maxSockets:10
};
var agent = new Agent(options);
var requestOptions = {
host:"www.google.com",
port:80,
agent:agent
};
var req = http.request(requestOptions);
req.end();
应用第三方请求模块简化HTTP请求
var reuqest = require('request');
request('http://www.acme.com:4001/something?page=2',function(error,response,body));
可以使用option对象来代替URL字符串。包含以下属性:
uri或者url:
method:
headers:
qs:作为查询字符串附加到URL后的名称-值对。
body:请求主体,必须是缓冲区或者字符串。
form:将请求主体设置成查询字符串的形式。增加请求头内容类型为:application/x-www-form-urlencoded;charset=utf-8.
json:请求主体设置为json形式,内容类型为application/json。
followRedirect:跟随具有状态码为3xx的响应。默认为true.
maxRedirects:跟随重定向的最多次数,默认为10.
onResponse:如果为true则回调函数将会在response事件发生时被调用。
encoding:
pool:表示请求代理的哈希对象。如果忽略则使用全局套接字池。
pool.maxSockets:
timeout:
————————————————
版权声明:本文为CSDN博主「xiaoerjun」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xiaoerjun/article/details/56012037