网络编程:构建 HTTP服务

1. http 模块

Node的 http 模块包含对HTTP处理的封装。在Node中,HTTP服务继承自TCP服务器( net 模块),它能够与多个客户端保持连接,由于其采用事件驱动的形式,并不为每一个连接创建额外的线程或进程,保持很低的内存占用,所以能实现高并发。HTTP服务与TCP服务模型有区别的地方在于,在开启 keepalive 后,一个TCP会话可以用于多次请求和响应。TCP服务以 connection为单位进行服务,HTTP服务以 request 为单位进行服务。 http 模块即是将 connection 到 request 的过程进行了封装,示意图如下图:

                      

1.1. http报文

我们用一个小例子来展示http的一个完整报文:

编写最简单的http服务程序并启动:http_server.js

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

然后使用curl工具进行请求:

xiao@uXiao:~/nodejs/深入浅出nodejs/chapter7$ curl -v http://127.0.0.1:1337/
*   Trying 127.0.0.1:1337...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 1337 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:1337
> User-Agent: curl/7.65.3
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Date: Thu, 02 Jan 2020 09:35:38 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
< 
Hello World
* Connection #0 to host 127.0.0.1 left intact

从上述信息中我们可以看到这次网络通信的报文信息分为四个部分,

第一部分内容为经典的TCP的3次握手过程,如下所示:

* About to connect() to 127.0.0.1 port 1337 (#0)
* Trying 127.0.0.1...
* connected
* Connected to 127.0.0.1 (127.0.0.1) port 1337 (#0)

第二部分是在完成握手之后,客户端向服务器端发送请求报文,如下所示:

GET / HTTP/1.1
User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
Host: 127.0.0.1:1337
Accept: */*

第三部分是服务器端完成处理后,向客户端发送响应内容,包括响应头和响应体,如下所示:

< HTTP/1.1 200 OK
< Content-Type: text/plain
< Date: Sat, 06 Apr 2013 08:01:44 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
Hello World

最后部分是结束会话的信息,如下所示:

* Connection #0 to host 127.0.0.1 left intact
* Closing connection #0

从上述的报文信息中可以看出HTTP的特点,它是基于请求响应式的,以一问一答的方式实现服务,虽然基于TCP会话,但是本身却并无会话的特点。

2. 构建示例

下面模拟实现一个简单的文件服务器:http_file_server.js

//实现一个静态文件服务器
var fs = require('fs');
var http = require('http');
var url = require('url');
//创建一个服务器
http.createServer( function(req,res) {
    if (req.url != "/favicon.ico"){
        var urlObj = url.parse(req.url,true,false);
        console.log(urlObj.pathname);
        fs.readFile('.' + urlObj.pathname,  function(err,data) {
                if (err){
                        res.writeHead(404, {'Content-Type': 'text/plain'});
                        res.end(JSON.stringify(err));
                        return;
                }
                console.log(data.toString());
                //将文件的内容写入res响应对象
                res.writeHead(200, {'Content-Type': 'text/plain'});
                res.end(data);
        });
    }
}).listen(8080);

在http_file_server.js同一目录下准备好一个测试文件test_json.json,然后编写客户端程序test_http_client.js :

var http = require('http');
var options = {
        hostname: '127.0.0.1',
        port: 8080,
        path: '/test_json.json',
        method: 'GET'
};
var req = http.request(options, function(res) {
        console.log('STATUS: ' + res.statusCode);
        console.log('HEADERS: ' + JSON.stringify(res.headers));
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
                console.log(chunk);
        });
});

req.end();

启动服务端程序,然后运行客户端,输出为:

xiao@uXiao:~/nodejs/深入浅出nodejs/chapter7$ node test_http_client.js 
STATUS: 200
HEADERS: {"content-type":"text/plain","date":"Thu, 02 Jan 2020 10:28:03 GMT","connection":"close","transfer-encoding":"chunked"}
{
        "rule":{
          "namespace":"strategy",
          "name":"test_exp_1496234234223400",
          "version":0,
          "last_modify_time":1434234236819000,
          "log_rate":1023300,
          "schema_version":"hello_world!"
        }
 }

2.1 服务端分析

报文头:

HEADERS: {"content-type":"text/plain","date":"Thu, 02 Jan 2020 10:28:03 GMT","connection":"close","transfer-encoding":"chunked"}

影 响 响 应 报 文 头 部 信 息 的 API 为 res.setHeader() 和 res.writeHead() 。在上述示例中:res.writeHead(404, {'Content-Type': 'text/plain'});其分为 setHeader() 和 writeHead() 两个步骤。它在 http 模块的封装下,实际生成如下报文:

< HTTP/1.1 200 OK
< Content-Type: text/plain

我们可以调用 setHeader 进行多次设置,但只有调用 writeHead 后,报头才会写入到连接中。除此之外, http 模块会自动帮你设置一些头信息。
报文体部分:

报文体部分则是调用 res.write() 和 res.end() 方法实现,后者与前者的差别在于 res.end() 会先调用 write() 发送数据,然后发送信号告知服务器这次响应结束,响应结果如下所示:

响应结束后,HTTP服务器可能会将当前的连接用于下一个请求,或者关闭连接。值得注意
的是,报头是在报文体发送前发送的,一旦开始了数据的发送, writeHead() 和 setHeader() 将不
再生效。这由协议的特性决定。
另外,无论服务器端在处理业务逻辑时是否发生异常,务必在结束时调用 res.end() 结束请
求,否则客户端将一直处于等待的状态。当然,也可

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Linux多线程服务端编程:使用muduo C++网络库》是一本介绍使用muduo C++网络库进行多线程服务端编程的电子书。该书由陈硕所著,适用于想要学习Linux多线程网络编程的开发人员。 本书从基础概念开始,详细介绍了多线程网络编程的原理和技术,并结合muduo C++网络库的使用示例,演示了如何开发高性能、稳定的网络服务端程序。 muduo C++网络库是一个基于事件驱动的网络编程库,它采用了Reactor模式,提供了高效的异步IO操作。该库封装了多线程、多进程、事件等相关操作,使得开发者可以简单、快速地开发网络服务端应用。 在本书中,作者通过具体的实例和代码示例,讲解了muduo C++网络库的使用方法和注意事项。书中内容分为多个章节,包括网络编程基础、IO复用、事件回调、线程同步、线程池等,涵盖了开发者在实际项目中可能遇到的各种情况。 通过学习《Linux多线程服务端编程:使用muduo C++网络库》,读者可以了解到多线程服务端编程的基本原理和技术,掌握使用muduo C++网络库进行高效开发的方法,并能够开发出高并发、高性能的网络服务端应用。 总之,该书是一本实用的网络编程指南,对于想要学习Linux多线程网络编程以及使用muduo C++网络库的开发人员来说,具有较高的参考价值。 ### 回答2: 《Linux 多线程服务端编程:使用 muduo C++ 网络库》是一本介绍如何使用 muduo C++ 网络库进行 Linux 多线程服务端编程的指南。该书主要目的是教读者如何构建高性能、可扩展的网络服务端应用程序。 该书首先介绍了多线程编程的基础知识,包括线程创建、线程同步与互斥、线程安全的数据结构等内容。然后,书中详细介绍了 muduo C++ 网络库的使用方法,包括网络编程基础、事件驱动模型、网络编程的设计模式等。读者可以通过学习这些内容,了解如何使用 muduo C++ 网络库来构建高性能的多线程服务端。 该书还介绍了业界常用的网络协议及其实现原理,例如 TCP/IP、HTTP 协议等。通过学习这些知识,读者可以更好地理解网络编程的工作原理,从而更好地设计和实现自己的网络服务端应用程序。 此外,书中还涵盖了一些实际案例和实战经验,读者可以通过这些案例了解如何应对常见的网络编程问题,并且学习到一些实际的开发技巧和调试技巧。 总而言之,《Linux 多线程服务端编程:使用 muduo C++ 网络库》是一本非常实用的指南,可以帮助读者快速入门多线程服务端编程,并且掌握使用 muduo C++ 网络库构建高性能的网络服务端应用程序的技巧。无论是初学者还是有一定网络编程经验的开发者,都可以从这本书中获得很多有价值的知识和经验。 ### 回答3: 《Linux 多线程服务端编程:使用 muduo C++ 网络库》是一本关于使用muduo C++网络库进行Linux多线程服务端编程的书籍。本书以muduo C++网络库为基础,深入讲解了多线程服务端编程的相关知识和技巧。 本书主要内容包括: 1. muduo库的介绍:介绍了muduo库的特性、设计思想和基本用法。muduo库是基于Reactor模式的网络库,提供了高效的事件驱动网络编程框架,有助于开发者快速搭建高性能的网络服务端。 2. 多线程编程的基础知识:介绍了多线程编程的基本概念和相关的线程同步和互斥机制,如互斥锁、条件变量等。并讲解了如何正确地使用这些机制,以保证多线程程序的正确性和高效性。 3. muduo C++网络库的使用:详细介绍了muduo库的线程模型、事件驱动机制和网络编程接口。通过实例代码和示意图,演示了如何使用muduo库构建一个多线程的网络服务端,包括创建监听套接字、事件的注册和处理、多线程任务分配等。 4. 高性能服务端的设计和优化:讲解了如何设计和优化高性能的多线程服务端。包括使用线程池提高并发处理能力、使用非阻塞IO提升数据处理效率、优化网络通信性能等方面的内容。 该书适合具有一定Linux编程基础的开发人员学习和参考。通过学习该书,读者可以掌握使用muduo C++网络库进行多线程服务端编程的技巧,提升服务端的性能和可靠性。同时,也可了解到网络编程领域的一些高级技术和最佳实践。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值