Paging
此篇是在我在OSTEP中看到内存虚拟化分页这一章时所遇到的。需要注意的是,此篇写时我还有点感冒后遗症,脑袋不大清晰,有些地方逻辑会存在混乱,谅解吧。
前情提醒,在本次学习中,我使用的代码将会是llfc大佬的代码,因为实在是懒的敲,这段博客可以视为是我个人的一个笔记。具体的可以去看llfc大佬的个人博客喵
在网络编程中,联系端对端的基础单位是一个套接字,对于asio来说,其实现了一层自己的框架,或者说规则。其对于使用其来开发的网络编程中进行了一系列的封装。在这其中,终端该概念,就是基于套接字进行的封装。但是需要注意的是,终端节点本身并不是一个套接字,只有对其进行进一步的包装,其才能成为一个合格的套接字。
我们来看到对应的创建终端节点的代码。正如在之前的tinyweb去创建一个套接字的前置工作一样,我们这里也需要对于终端节点的构造进行一些前置准备。简单来说,为了生成一个终端节点,我们需要先去包装一个ip地址以及对应的窗口。类比对应的getaddrinfo系统调用即使前俩个参数的信息。那么对于ip地址的构建,其又存在着什么规则呢,请看看下面源码。
1 | int client_end_point() |
这里以客户端的终端节点创建为例,在创建节点前,我们需要优先知道所需要连接的服务器端的ip地址。有了这个ip地址,再配合我们自己声明的一个用于储存错误代码的boost::system::error_code
成员,我们可以进行make_address
函数的调用。该函数位于asio::ip
域下,使用一个ip地址和一个错误储存码来构建一个在asio中合格意义的ip地址。
前面的传入ip地址只是一个字符串,直接使用其来进行通信具有太多的风险,使用类来对其进行包装能使得程序更加健壮。
对于第二个参数,顾名思义,其是一个错误储存码,储存着在该次创建过程中的状态信息,当且仅当在函数正常返回时返回0.对于这种简单的错误处理,之后将不再进行赘述。
在创建完一个封装完毕的ip地址之后,我们可以使用其来构建我们的ip地址。在asio中,相对于之前直接使用c系统调用来进行创建的最大不同点是,我们在这里不必再对其进行一些属性信息在传递参数上的设置。更简单的。C++实现的asio通过类作用域来进行一个区分,这样既显式的指出了我们在创建一个终端节点时的繁琐,而且大大提高了使用的连接的可读性。
1 | asio::ip::tcp::endpoint ep(ip_address,port_num); |
在该类对象创建中,通过传入一个ip地址和对应的端口号,我们可以对其进行一个绑定,由于这是一个客户端,所以这里指定的其实就是对应的服务器端的服务提供位置。除此之外,还可以看到,在该类成员构造之前,我们使用了一系列的类作用域限定符。通过ip::tcp::endpoint
这种层次上的逻辑,我们不难推断出在该终端节点中我们使用的协议以及该成员变量的用处。
接下来来看到对应与客户端节点的服务器端节点的创建,正如一般的网络编程的服务器端设置比客户端设置简单一样。对应的服务器端由于使用的端口地址被固定为了本地地址,所以这里的终端节点的创建也更加简单。但是,这是基于简单的实现的。在asio或者更加现代的网络库中,对于机器监听的设置更加灵活。对于一个进程所请求的监听设置,其可能不再局限于一个
1 | int server_end_point(){ |
在这里,我们需要对于一个计算机上的ip地址再进行一下分析。在很多情况下,我们其实都认为一个计算机存在一个自己唯一的ip地址。事实上也确实如此,但是!这是相对于整个互联网网络来说的。对于一个计算机本身,其还存在着一系列的用于本身的测试等作用的地址,就比如我们很熟悉的本地回环地址localhost
。这个回环地址与计算机在公网上的地址是不一样的。
回到我们这里的服务器端的地址的构建,这里其实本质上是将所有的本地使用的地址都绑定到了对应的类结构上了。这个可以去查看对应的asio::ip::address
源码去了解。对应的,一但使用any进行对应的服务器ip地址的构建,其将能够接受来自本机上所有不同属性的请求。就比如,来自本地的IPV6协议网络请求,来自局域网和公网的网络请求等。但是,这并不意味着使用any绑定后该进程能够拦截所有来自外部的请求。对应的请求还是只能传输给对应的端口。这里也就是不必关心出现问题的原因。
在创建出对应的IP地址之后,接下来的终端节点创建工作与客户端无异,这里就直接跳过了。