nodejs学习笔记3

构建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:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值