期待你的分享

0%

计算机基础

网络

DNS解析过程

  1. 浏览器输入域名http://www.baidu.com ,操作系统会先检查hosts文件是否有这个网址的映射关系,如果有,就先调用这个IP,完成域名解析
  2. 如果hosts里面没有,则查找本地DNS解析器缓存,是否有这个网址的映射关系,如果有,就先调用这个IP,完成域名解析
  3. 如果还是没有,则会查找TCP/IP参数中设置的首选DNS服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置的区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性
  4. 如果要查询的域名不由本地DNS服务器区域解析,但该服务器已经缓存了此网址映射关系,则调用这个IP地址映射,此解析不具有权威性
  5. 如果本地DNS服务器区域解析与缓存都失效,则根据本地服务器的设置(是否设置转发器)进行查询,如果未用转发器模式,本地DNS就把请求发送给13台根DNS,根DNS收到请求后会判断这个域名(.com)是谁来授权管理,并返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP后,将会请求这台服务器,如果这台服务器自己无法解析,它就会找一个管理.com域名的下一级DNS服务器地址(http://baidu.com)给本地DNS服务器。当本地服务器收到地址后,就会找http://baidu.com域服务器,重复上面的动作,进行查询,知道找到www.baidu.com的主机
  6. 如果用的是转发模式,此DNS服务器就会把请求转发给上一级服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把请求转发给上上级,以此循环。不管本地DNS服务器用的是转发,还是根提示,最后都是把结果返回给本地DNS服务器,再由本地DNS服务器返回给客户机。

请求过程用的是UDP还是TCP?

UDP,UDP发送快

为什么是13台根服务器?

为了做Prime QueryRoot Servers性价比达到最高,肯定是一个包能放多少东西就塞多少东西,所以把所有Root Servers的结果都塞进去,刚好能塞14个,不全用就塞13个吧,留下一点东西以备后患,留待扩展。

I/O

同步、异步:消息通信机制

阻塞,非阻塞:等待状态

五种I/O模型:

  • 阻塞I/O
  • 非阻塞I/O
  • I/O多路复用
  • 信号驱动I/O
  • 异步I/O

select函数

多路复用I/O

1
int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout);

机制

select提供一个fd_set数据结构,实际上是一个long型的数组,里面的每个元素都与能打开的文件句柄建立联系,当调用select时,由内核根据IO状态修改fd_set的内容,由此通知select()的进程某个socket或文件可读

优点

一个线程处理多个I/O请求

问题

  1. 每次调用select时,都要把fd_set集合 从用户态拷贝到内核态,开销大
  2. 每次调用select时,都要遍历一遍fd_set集合,时间长
  3. 为了减少数据拷贝带来的性能损耗,fd_set的集合大小有限制,限制为1024(不可改变)

poll函数

1
2
3
4
5
6
7
int poll(struct pollfd *fds, nfds_t nfds, int timeout);

typedef struct pollfd {
int fd; // 需要被检测或选择的文件描述符
short events; // 对文件描述符fd上感兴趣的事件
short revents; // 文件描述符fd上当前实际发生的事件
} pollfd_t;

与select类似,但是没有大小限制

epoll函数

事件驱动I/O

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 创建一个epoll句柄,size代表描述符数量,成功时返回epoll句柄描述符,失败时返回-1
int epoll_create(int size);
// 注册要监听的事件类型:注册,修改,删除
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
// 等待事件的就绪,成功时返回就绪的事件数目,失败时返回-1,等待超时返回0
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;

epoll没有描述符个数限制,使用一个文件描述符管理多个描述符,将用户关心的文件描述符的事件存放到内核的一个事件表中,这样用户态和内核态的空间拷贝只需一次

触发方式:

  • 水平触发(LT):默认,当epoll_wait检测到某描述符事件就绪并通知应用程序时,应用程序可以不立即处理;下次调用epoll_wait时,会再次通知该事件(1->1)
  • 边缘触发(ET):当epoll_wait检测到某描述符事件就绪并通知应用程序时,应用程序必须处理该事件;如果不处理,下次调用epoll_wait时,不会通知该事件。(直到其他操作导致该描述符变为未就绪状态时,也就是边缘触发只在状态从未就绪到就绪通知一次)(0->1)