本文简要介绍一下BIND9中的UDP数据处理,包括如何创建socket、设置什么socket参数、多线程环境中如何让多个线程读取53端口的数据等等。

BIND9的架构采用event-driven和task-based。对于像TCP这样的事件采用event-driven来等待读写时间,而在多线程方面,采用task-based的方式,服务器启动时由task_manager创建一系列干活的线程task(CPU个数个),然后外部的用户通过调用isc_task_send函数将事件挂到task_manager的事件队列中,各线程(task)从这个事件队列中获得要干的活,开始干活。

对于UDP而言,BIND9的做法是在主进程中创建好UDP socket,然后各个线程都在这个fd上通过recvmsg来收取消息并处理(由于recvmsg是线程安全的,所以多线程环境中可以这样用而不用加锁)

关键流程如下所示:

1, 主进程:ns_interface_listenudp <--ns_interface_setup <-- do_scan <-- ns_interfacemgr_scan0 <-- ns_interfacemgr_scan <-- scan_interfaces <--load_configuration <-- run_server <-- ns_server_create <-- setup <-- main

其中ns_interface_listenudp的作用是在给定的IP地址和端口上监听UDP事件:

 首先,调用dns_dispatch_getudp()从interface manager中获取到udpdispatch(如果没有,就创建一个),其中在创建udpdispatch的dispatch_createudp函数中:
   a, 会调用get_udpsocket()创建新的isc_socket_t对象。get_udpsocket()中关键的是open_socket(sockmgr, localaddr,ISC_SOCKET_REUSEADDRESS, &sock)函数,它创建一个socket,并调用bind绑定IP地址和端口。关键步骤是:

  1),调用socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);创建socket.
2),调用 flags = fcntl(fd, F_GETFL, 0); flags |= PORT_NONBLOCK; ret = fcntl(fd, F_SETFL, flags);将socket设置为非阻塞模式
3),调用setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on))设置套接字选项
4),调用bind(sock->fd, &sockaddr->type.sa, sockaddr->length) 为该socket绑定IP地址和端口
 
    b, socket创建好,bind好之后。分配64个task(这些task存在dispatch->task[64]数组中),然后为dispatch->ctlevent分配事件,它调用distroy_disp来销毁一个dispatch(当然其中会调用closesocket来关闭一个socket).
 
  2,通过getudp获取到udpdispatch之后,就调用ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus, ifp, ISC_FALSE);来创建线程监听这个interface ifp了:
      创建ns_g_cpu个client,然后调用ev = &client->ctlevent;  isc_task_send(client->task, &ev);开始干client_start活
     其中创建client的时候,client->sendevent干client_senddone活;  client->recvevent干client_request活; client->ctlevent干client_start活
 
3, client_start
       对于UDP,执行client_udprecv()函数,client_udprecv的核心是执行isc_socket_recv2函数,isc_socket_recv2的核心是执行socket_recv();socket_recv的核心是doio_recv()。
      doio_recv()中就是recvmsg()系统调用。

工作线程

上面的isc_task_send(client->task, &ev)被调用后,主进程就把任务丢给了工作线程去做。

示意图如下所示:

从上图中可以看到,当线程通过recvmsg接收到数据后会交给队列中的线程执行client_request()函数;client_request就是解包处理DNS请求。

如果线程通过recvmsg没有接收到数据,则将这个fd加入到epoll的监听队列中(BIND9有一个单独的线程执行epoll循环),当这个fd上有读事件的时候,epoll线程会调用internal_recv()处理UDP数据,internal_recv的核心依然是doio_recv函数。

BIND9源码分析之UDP数据处理的更多相关文章

  1. Nginx学习笔记(四) 源码分析&socket/UDP/shmem

    源码分析 在茫茫的源码中,看到了几个好像挺熟悉的名字(socket/UDP/shmem).那就来看看这个文件吧!从简单的开始~~~ src/os/unix/Ngx_socket.h&Ngx_s ...

  2. BIND9源码分析之acl 的实现

    BIND配置中一大堆一大堆的acl,什么allow-query, allow-recursion, allow-update还有view的match-clients等等等等. acl中的主要存储的就是 ...

  3. BIND9源码分析之 多个view的情况下如何做dynamic update

    BIND中view的存在提供了一种较好的智能DNS方案,BIND可以根据用户的来源IP为其返回不同的Resource Record. 但是关于DNS动态更新的RFC2136中并没有提及view(vie ...

  4. 66、Spark Streaming:数据处理原理剖析与源码分析(block与batch关系透彻解析)

    一.数据处理原理剖析 每隔我们设置的batch interval 的time,就去找ReceiverTracker,将其中的,从上次划分batch的时间,到目前为止的这个batch interval ...

  5. Duilib源码分析(六)整体流程

    在<Duilib源码分析(一)整体框架>.<Duilib源码分析(二)控件构造器—CDialogBuilder>以及<Duilib源码分析(三)XML解析器—CMarku ...

  6. jQuery源码分析系列(36) : Ajax - 类型转化器

    什么是类型转化器? jQuery支持不同格式的数据返回形式,比如dataType为 xml, json,jsonp,script, or html 但是浏览器的XMLHttpRequest对象对数据的 ...

  7. 介绍开源的.net通信框架NetworkComms框架 源码分析

    原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 售价249英镑 我曾经花了 ...

  8. 《深入理解Spark:核心思想与源码分析》(前言及第1章)

    自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售 ...

  9. 《深入理解Spark:核心思想与源码分析》(第2章)

    <深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...

随机推荐

  1. UITableView与UIScrollView的一些问题(持续更新)

    UITableView的一些常用操作 --------------------------------------------------------------------------------- ...

  2. struts2 select 默认选中

    jsp: <s:select list="#{'1':'男','2':'女'}" name="sex"/> action: private Stri ...

  3. 仿LOL项目开发第七天

    仿LOL项目开发第七天 by 草帽 不知不觉已经写到了第七篇这种类型的博客,但是回过头看看之前写的,发现都只能我自己能看懂. 我相信在看的童鞋云里雾里的,因为我基本上没怎么详细讲一个脚本怎么用?但是你 ...

  4. [PHP] ubuntu16.04配置Lamp环境(搭建linux+apache+mysql+php7环境)

    reference : http://blog.csdn.net/Abyss_sliver/article/details/77621404 好久没有在Linux环境下进行开发了,比较常用的还是win ...

  5. 常用数学函数篇abs acos asin atan ceil cos exp frexp ldexp log pow sin sinh sqrt tan tanh

    abs(计算整型数的绝对值) 相关函数 labs, fabs 表头文件 #include<stdlib.h> 定义函数 int abs (int j) 函数说明 abs()用来计算参数j的 ...

  6. 学习笔记:A*算法

    简易地图 如图所示简易地图, 其中绿色方块的是起点 (用 A 表示), 中间蓝色的是障碍物, 红色的方块 (用 B 表示) 是目的地. 为了可以用一个二维数组来表示地图, 我们将地图划分成一个个的小方 ...

  7. Redhat Linux FTP配置

    文件传输协议(FTP:FileTransfer Protocol)使得主机间可以共享文件. FTP 使用 TCP 生成一个虚拟连接用于控制信息,然后再生成一个单独的 TCP 连接用于数据传输.控制连接 ...

  8. WebViewClient 简介 API 案例

    代码位置:https://github.com/baiqiantao/WebViewTest.git 设计思想理解 在WebView的设计中,不是什么事都要WebView类干的,有相当多的杂事是分给其 ...

  9. js 获取读取cookie

    // --- 设置cookie function setCookie(sName, sValue, expireHours) {     var cookieString = sName + &quo ...

  10. Android -- 触摸Area对焦区域(更新)

    老早就想找关于不同点击不同地方的对焦,但是一直没有找到,现在项目又需要这个功能,又跑出来找找,最后还是找到啦~~关于对焦更多的是关于自动对焦. 废话不多说,直接来干货,主要是setFocusAreas ...