目录
一. 创建HTTP服务器
调用http模块 var http = require('http');
step1 创建服务器对象
var server = http.createServer([requestListener]); //接受客户端发来的请求和响应客户端
另一种方法: server.on('request', function(request, response){ });
注:requestListener 请求监听函数,相当于 function(request, response);
step2 监听端口
server.listen(port, [host], [backlog], [callback]);
解析:
port:端口号;
host:如果指定,只能通过Host访问服务,如果不指定,任意的服务端都可以访问服务。
host:127.0.0.1,则只有本机可以访问服务。
backlog:等待队列中客户端连接的最大数量,超过则拒绝客户端连接,默认值为511,即默认同时支持511个客户端请求。
callback:listening事件,或使用server.on('listening', function(){})
demo1:演示listen中的callback
server1.js
var http = require('http');
//1. 创建服务器对象 var server = http.createServer([requestListener]);
var server = http.createServer(function(request, response){
});
//2. 监听端口 server.listen(port, [host], [backlog], [callback]);
server.listen(3456, "127.0.0.1", function(){
console.log('服务器正在监听3456端口');
});
运行结果:
demo2:测试close
server2.js
var http = require('http');
var server = http.createServer(function(req, res){
}).listen(3456,'127.0.0.1');
server.on('listening', function(){
console.log('服务端开始监听3456端口');
server.close();
});
server.on('close', function(){
console.log('服务器已经被关闭');
});
运行结果:
demo3:当端口被占用时,如何处理,测试error事件
server.js
var http = require('http');
var server = http.createServer(function(req, res){
}).listen(3456, '127.0.0.1');
server.on('error', function(e){
if(e.code == "EADDRINUSE")
{
console.log('服务器地址及端口已经被占用');
}
});
运行结果:先运行,然后再重新开一个窗口,输入相同命令:node server.js
demo4:connection事件
server4.js
var http = require('http');
var server = http.createServer(function(req, res){
}).listen(3456, '127.0.0.1');
//这里区分于服务器端监听, 先监听,当网页输入127.0.0.1:3456时,客户端才会建立连接
server.on('connection', function(socket){
console.log('客户端连接已经建立');
});
server.on('listening', function(){
console.log('服务端开始监听3456端口');
});
运行结果:服务端开始监听3456端口后,输入网址127.0.0.1:3456,客户端建立连接
出现两次连接已经建立是因为网页图标也会发出一次请求
demo5:测试服务端超时
var http = require('http');
var server = http.createServer(function(req, res){
}).listen(3456, '127.0.0.1');
server.setTimeout(3*1000, function(socket){
console.log('服务端超时');
console.log(socket);
});
测试服务端超时还可以用:
server.on('timeout', function(socket){ });
timeout = 3000;
运行结果:node server.js之后,在浏览器输入网址127.0.0.1:3456,显示服务端超时,并输出socket内容
二、获取客户端请求信息
method:GET、POST
url:path
headers:请求头
httpVersion:http版本(1.0和1.1)
socket:Socket对象
data:客户端传过来的数据
demo1
test01.js
var http = require('http');
var fs = require('fs');
var server = http.createServer(function(req, res){
console.log(req.url);
if(req.url != '/favicon.ico') //每个页面都有图标(路径+图标),这里过滤调图标的
{
var out = fs.createWriteStream('./request.txt');
out.write('客户端请求方法:'+ req.method + '\r\n');
out.write('客户端请求所有的url:' + req.url + '\r\n');
out.write('客户端请求头:' + JSON.stringify(req.headers) + '\r\n');
out.end('客户端请求的HTTP版本:' + req.httpVersion);
}
res.end();
}).listen(3456, '127.0.0.1');
运行结果:输入node test01.js后,浏览器输入网址127.0.0.1:3456/abc.html,如下出现两次申请路径,是因为网页页面有图标(路径+路标),也会发一次请求。
三、客户端请求的data和end事件
data:当服务端接收到数据时触发
end:数据接收完毕时触发
demo1
data_end.js
var http = require('http');
var server = http.createServer(function(req, res){
if(req.url !== '/favicon.ico')
{
//服务端接收到数据时触发
req.on('data', function(data){
console.log('服务器接收到的数据:' + decodeURIComponent(data));
});
//数据接收完毕时触发
req.on('end', function(){
console.log('客户端请求数据已经全部接收完毕');
});
}
res.end();
}).listen(3456, '127.0.0.1');
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Node.js的data事件与end事件</title>
</head>
<body>
<form id="form1" action="http://localhost:3456/test/data_end.js" method="post">
姓名: <input type="text" name="name" value="李宁"><br/>
职位:<input type="text" name="job" value="CEO"><br/>
<input type="submit" value="提交" />
</form>
</body>
</html>
运行结果:(先起server进行监听,然后运行html文件,点击submit提交文本数据)
四、解析URL字符串和查询字符串
示例:
一般情况下,一个完整的地址为: http://localhost:3456/abc/test.js?name=bill&age=30
url则为: /abc/test.js?name=bill&age=30
demo1
querystring.js
var http = require('http');
var url = require('url');
var querystring = require('querystring');
var server = http.createServer().listen(3456, '127.0.0.1');
server.on('request', function(req, res){
if(req.url != '/favicon.ico')
{
res.write('<html><head><meta charset="utf-8"/></head>');
var url_parts = url.parse(req.url);
console.log('url_parts:' + url_parts);
var qs = querystring.parse(url_parts.query);
console.log(qs);
if(qs.name)
{
console.log('name:' + qs.name);
}
if(qs.age)
{
console.log('age:' + qs.age);
}
switch(url_parts.pathname)
{
case '/':
case '/index.html':
res.write('<body>您当前正在访问网站首页</body></html>');
break;
default:
res.write('<body>您当前正在访问的页面:' + url_parts.pathname + '</body></html>');
}
}
res.end();
});
五、向客户端发送数据
1.content-type:内容类型
2.location:用于将客户端重定向到另一个URL地址
3. content-length:内容长度
4. set-cookie:在客户端创建一个cookie
5. content-encoding:用于指定服务器端响应内容的编码方式
6. Cache-Control:用于开启缓存机制
7. Expires:用于指定缓存过期时间
demo1 : write head
test01.js
var http = require('http');
var server = http.createServer(function(req, res){
if(req.url != '/favicon.ico')
{
res.writeHead(200, {'Content-Type':'text/plain'}); //发送消息头
res.write('hello'); //发送相应的内容
console.log('已经向客户端发送数据');
res.end();
}
}).listen(3456, '127.0.0.1');
运行结果:
demo2: set Header
test02.js
var http = require('http');
var server = http.createServer(function(req, res){
if(req.url != '/favicon.ico')
{
res.setHeader("Content-Type", "text/plain");
res.setHeader("Access-Control-Allow-Origin", "http://localhost");
//res.removeHeader("Content-Type"); //移除头
res.write('Are you ok?');
console.log(res.getHeader("Content-Type"));
}
res.end();
}).listen(3456,"127.0.0.1");
运行结果:
六. headerSent属性
boolean类型,如果响应头已经发送到客户端,true,否则为false
writeHead
setHeader
demo1:write_head_sent
var http = require('http');
var server = http.createServer(function(req, res){
if(req.url != '/favicon.ico')
{
if(res.headerSent)
console.log('响应头已发送');
else
console.log('响应头未发送');
res.writeHead(200, {'Content-Type':'text/html'}); //写一个响应头
if(res.headerSent)
console.log('响应头已发送');
else
console.log('响应头未发送');
res.write('<html><head><meta charset="utf-8"/></head>');
res.write('你好');
}
res.end();
}).listen(3456, "localhost");
demo2:set_head_sent
var http = require('http');
var server = http.createServer(function(req, res){
if(req.url != '/favicon.ico')
{
res.setHeader('Content-Type','text/html'); //setHeader并未发送响应头
if(res.headerSent)
console.log('响应头已发送');
else
console.log('响应头未发送');
res.write('<html><head><meta charset="utf-8"/></head>');
if(res.headerSent)
console.log('响应头已发送');
else
console.log('响应头未发送');
res.write('你好');
}
res.end();
}).listen(3456, "localhost");
七. http.write和http.end方法
(1)boolean write(chunk, [encoding]);
析:
chunk:向客户端发送的数据,String或Buffer
encoding:指定String的字符编码,默认是utf8
返回值为布尔类型,true表示chunk写到了缓存中,false表示chunk未写到缓存中
(2)end([chunk], [encoding]);
析:
作用:
1. 结束向客户端写入数据的动作
2. 将缓存中剩余的数据发送到客户端
demo1 write_end
var http = require('http');
var fs = require('fs');
var server = http.createServer(function(req, res){
if(req.url != '/favicon.ico')
{
fs.readFile('t.txt', function(err, data){
if(err) console.log('读取文件时发生错误');
else
{
var flag = res.write(data);
//当data写入缓存,flag为true,否则为false
console.log(flag);
res.end();
}
});
}
}).listen(3456);
八. timeout事件
如果指定callback,超过时间后,就会调用callback, 如果未指定callback,服务端就会自动关闭与客户端的Socket连接
response.setTimeout(ms, [callback])
response.on(callback);
析:
ms:超时时间(毫秒)
callback:超时回调函数
demo1
timeout.js
var http = require('http');
var server = http.createServer(function(req, res){
if(req.url != '/favicon.ico')
{
//设置超时时间为1秒
res.setTimeout(1000);
//通过on方法注册callback
res.on('timeout', function(){
console.log('响应已经超时');
});
setTimeout(function(){
res.setHeader('Content-Type','text/html');
res.write("<html><head><meta charset='utf-8'/></head>");
res.write('hello');
res.end();
}, 2000);
}
}).listen(3456);
九. 请求Web数据
GET或POST
http.request(options, [callback]);
hostname:'www.baidu.com'
port:80
path:'/'
method:GET
demo1 request_http.js
var http = require('http');
var options = {
hostname:'geekori.com',
port:80,
path:'/',
method:'GET'
};
var req = http.request(options, function(response){
console.log('状态码:' + response.statusCode);
console.log('响应头:' + JSON.stringify(response.headers));
response.setEncoding('utf8');
response.on('data', function(chunk){
console.log('响应内容:' + chunk);
});
});
req.end();
demo2 request_https.js
var https = require('https');
var options = {
hostname:'geekori.com',
port:443, //注意https的端口是443
path:'/',
method:'GET'
};
var req = https.request(options, function(response){
console.log('状态码:' + response.statusCode);
console.log('响应头:' + JSON.stringify(response.headers));
response.setEncoding('utf8');
response.on('data', function(chunk){
console.log('响应内容:' + chunk);
});
});
req.end();
十. 请求Web数据中的事件和终止请求
response:从服务器返回数据时会触发
error:发送错误触发
socket:建立socket时会触发
timeout:发生超时会触发
request.abort()
demo1:request_event.js
var http = require('http');
var options = {
hostname:'geekori.com',
port:80,
path:'/',
method:'GET'
};
var request = http.request(options, function(response){
console.log('状态码:' + response.statusCode);
console.log('响应头:' + JSON.stringify(response.headers));
response.setEncoding('utf8');
response.on('data', function(chunk){
console.log('响应内容:' + chunk);
});
});
request.on('socket', function(socket){
console.log('socket已经建立');
})
request.end();
demo2:response
var http = require('http');
var options = {
hostname:'geekori.com',
port:80,
path:'/',
method:'GET'
};
var request = http.request(options, function(response){
console.log('状态码:' + response.statusCode);
console.log('响应头:' + JSON.stringify(response.headers));
response.setEncoding('utf8');
response.on('data', function(chunk){
console.log('响应内容:' + chunk);
});
});
request.on('response', function(response){
console.log('response');
});
request.on('socket', function(socket){
console.log('socket已经建立');
});
request.end();
demo3:error
var http = require('http');
var options = {
hostname:'geekori.com',
port:8888,
path:'/',
method:'GET'
};
var request = http.request(options, function(response){
console.log('状态码:' + response.statusCode);
console.log('响应头:' + JSON.stringify(response.headers));
response.setEncoding('utf8');
response.on('data', function(chunk){
console.log('响应内容:' + chunk);
});
});
request.on('error', function(err){
if(err.code == 'ECONNRESET')
{
console.log('socket端口超时');
}
else
{
console.log('在请求数据的过程中发生错误,错误代码:' + err.code);
}
});
//设置超时时间
request.setTimeout(2000);
request.on('socket', function(socket){
console.log('socket已经建立');
});
request.end();
demo4:timeout
var http = require('http');
var options = {
hostname:'geekori1.com', //
port:80,
path:'/',
method:'GET'
};
var request = http.request(options, function(response){
console.log('状态码:' + response.statusCode);
console.log('响应头:' + JSON.stringify(response.headers));
response.setEncoding('utf8');
response.on('data', function(chunk){
console.log('响应内容:' + chunk);
});
});
request.on('error', function(err){
if(err.code == 'ECONNRESET')
{
console.log('socket端口超时');
}
else
{
console.log('在请求数据的过程中发生错误,错误代码:' + err.code);
}
});
//设置超时时间
request.setTimeout(2000, function(){
request.abort(); //中断请求
});
request.on('socket', function(socket){
console.log('socket已经建立');
});
request.end();
十一. 案例:自定义与客户端交互的服务器
服务端:custom_server.js
var http = require('http');
var server = http.createServer(function(request, response){
request.on('data', function(data){
console.log('从客户端接收到的数据:' + decodeURIComponent(data));
});
response.write('hello world');
response.end();
}).listen(3456);
客户端:custom_client.js
var http = require('http');
var querystring = require('querystring');
const postData = querystring.stringify({
'name':'Bill',
'age':40
});
var options = {
hostname:'localhost',
port:3456,
path:'/',
method:'POST',
headers:{
'Content-Type':'application/x-www-form-urlencoded',
'Content-Length':Buffer.byteLength(postData)
}
};
var req = http.request(options, function(response){
response.setEncoding('utf8');
response.on('data', function(data){
console.log('响应内容:' + data);
});
});
req.write(postData);
req.end();
十二. 创建HTTPS服务器
HTTP服务器和HTTPS服务器的区别:
HTTP服务器与客户端交互时,传输的数据都是明文;
HTTPS服务器与客户端交互时,传输的数据是加密形式的。