【课程笔记】HTTP服务器与客户端技术

目录

一. 创建HTTP服务器

step1  创建服务器对象

step2  监听端口

demo1:演示listen中的callback

demo2:测试close

 demo3:当端口被占用时,如何处理,测试error事件

 demo4:connection事件

 demo5:测试服务端超时

二、获取客户端请求信息

demo1

三、客户端请求的data和end事件

四、解析URL字符串和查询字符串

五、向客户端发送数据

demo1 : write head

 demo2: set Header

六. headerSent属性

demo1:write_head_sent

demo2:set_head_sent

七. http.write和http.end方法   

demo1 write_end

八.  timeout事件  

九. 请求Web数据

demo1 request_http.js

demo2 request_https.js

十. 请求Web数据中的事件和终止请求

demo3:error

demo4:timeout

十一. 案例:自定义与客户端交互的服务器

十二. 创建HTTPS服务器


一. 创建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服务器与客户端交互时,传输的数据是加密形式的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值