HTTP:
超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。1960年美国人Ted Nelson构思了一种通过计算机处理文本信息的方法,并称之为超文本(hypertext),这成为了HTTP超文本传输协议标准架构的发展根基。Ted Nelson组织协调万维网协会(World Wide Web Consortium)和互联网工程工作小组(Internet Engineering Task Force )共同合作研究,最终发布了一系列的RFC,其中著名的RFC 2616定义了HTTP 1.1。
tcp::resolver 一般和 tcp::resolver::query 结合用 , 通过query这个词顾名思义就知 道它是用来查询socket 的相应信息,一般而言我们关心socket的东东有address,port而已,通过tcp::resolver 很容易实现设置和查询,它通过query
把字符串格式的ip如192.168.0.200或主机名http:://localhost,端口“8080”等转化成socket内部表示格式,这样我们应用的时候可以直接使用字符串的形式,而且不用再担心socket的字节顺序转化问题。示例如下:
boost::asio:: io_service io_service ;
tcp::resolver resolver (io_service );
tcp::resolver::query query ("localhost" , "9000" );
TCP/IP 参考模型:
应用层,包括HTTP(超文本传输协议)、FTP(文件传输协议)、TELNET(远程登录)、SSH(安全外壳协议)、STMP(简单邮件发送)、POP3(收邮件):负责应用程序的网络访问,这里通过端口号来识别各个不同的进程。
端口号:
指的是:TCP/IP 协议中的端口,端口号范围0-65535
IP地址:
通常用户在表达IP地址时采用的是点分十进制表示的数值(或者冒号分开的十进制IPv6地址),而在socket编程中使用的二进制值,这就需要将两个值进行交换。
套接口(套接字):
是一个数据结构,他是网络中的节点进行通信的门户。它是网络进程的ID。网络通信是进程间的通信(不同计算机上的进程间的通信)。每一个节点(计算机或路由)都有一个网络地址,也就是IP地址。两个进程通信时,首先要确定各自所在的网络节点的IP地址,但是IP地址只能确定进程所在的计算机,而一个计算机可能运行着多个进程,所以套接口还需要包括端口号(PORT)。在一个计算机中,一个端口号一次只能分配给一个进程,在一个计算机中,端口号和进程是一一对应的关系。
端口号+网络地址(IP地址)=网络进程
Boost.Asio:
Asio:「异步 IO」(Asynchronous Input/Output),是一个 独立的 C++ 网络程序库,后来因为被 Boost 相中,才声名鹊起。
从设计上来看,Asio 相似且重度依赖于 Boost,与 thread、bind、smart pointers 等结合时,体验顺滑。从使用上来看,依然是重组合而轻继承,一贯的 C++ 标准库风格。
什么是「异步 IO」?
简单来说,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知。
Asio 的「I/O 操作」,主要还是指「网络 IO」,比如 socket 读写。
每个 Asio 程序都至少有一个 io_context
对象,它代表了操作系统的 I/O 服务(io_context
在 Boost 1.66 之前一直叫 io_service
),把你的程序和这些服务链接起来。
例如:
下面这个程序空有 io_context
对象,却没有任何异步操作,所以它其实什么也没做,也没有任何输出。
int main() {
boost::asio::io_context ioc;
ioc.run();
return 0;
}
io_context.run
是一个阻塞(blocking)调用,姑且把它想象成一个 loop(事件循环),直到所有异步操作完成后,loop 才结束,run
才返回。
这是一个名为Boost.Beast的新开源库,它使用Boost.Asio提供HTTP和WebSocket功能。它尽可能地模拟熟悉的Asio接口,并且有大量的文档
http 也是 TCP,在通信模块用asio做了一些辅助的工作:解析http协议,asio做TCP/UDP通信的,你可以发'a',也可以发“adadad”,随意发。而beast,http基于TCP的直接用了asio做了底层的通信,做了一些额外的工作,解析http协议。
建立一个io_context类,声明一个变量ioc(现在只是知道简单的应用就行),
声明一个解释器resolver的对象resolver,要给resolver传递一个参数,这个大括号括起来,这是C++11的列表初始化,以前用的函数使用圆括号括起来,来调用构造函数,C++11用了大括号。一般我们访问http://www.baidu.com,解释器resolver就是把www.baidu.com这个域名解释成一个标准IP,,最终解析成xxx.x.x.x,例如“127.0.0.8”。
向TCP中的socket,在写底层函数时候要创建套接字,而http中的socket是包装好的一个类class,实际上是声明了一个socket类的对象,极有可能是在构造函数中创建socket()的,在这里不做具体探究。
声明的这个对象resolver类中有一个resolve()函数,resolve()函数解析中传入了一个host(IP地址,传入"xxx.x.x.x"或者www.baidu.com也行,传IP还是域名经过解析后都变成一个IP了)和port,
解析之后链接,用connect()函数,记住其格式就行。
(注意:HTTP把数据的收发定义为请求request和响应,请求一般是客户端发的,响应是服务器)
连接之后,声明了一个request模板类-,模板参数string_body是字符串,声明了一个变量req,传递三个默认参数,1、http请求使用的方法为get。(http是命名空间,verb是一个枚举,他这个get请最终会转化成http协议里边的 )。2、target目标,例如:http://www.baidu.com:80/index.html,端口是80,但是http默认端口就是80,所以可以不写,target就是/index.html,version是版本,一般传给1.1就行了,这个请求就做好了,设置他的请求对象host,为啥设置,没有原因,记着就行,(host其实也可以不设置,解析器已经连接好了)。调用http命名空间中的write函数(相当于send),原先write的命名空间是 boost::beast::http,只不过给他定义了别名namespace http = boost::beast::http,主要是太长了。这几行代码实际上就是http协议实际上就是一个字符串,一般发过之后就要接收,先定一个buffer,flat_buffer是beast里边自己构造的没啥特别的。
接着声明reponse响应,响应对象用于接收(相当于recv),三行代码,dynamic_body是动态存储,read有阻塞作用,假如发出请求之后,服务器端一直不给回复,那就阻塞在这里,,将服务器传递回来的内容进行解析,定义一个stringstream,记住就行了,ss也是输出流,最终关闭socket,响应的内容都在res.dody()。