成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

編程實戰:如何在程序中解析域名

網絡 通信技術
網絡應用客戶端想要跟服務端通信,必須先向 DNS 服務器查詢域名對應的 IP 地址。舉個例子,讀者訪問我的網站 fasionchan.com 時,瀏覽器需要先根據域名查詢網站的 IP 地址,再和網站的 Web 服務器進行通信。

[[403061]]

本文轉載自微信公眾號「小菜學編程」,作者fasionchan。轉載本文請聯系小菜學編程公眾號。

由于域名比 IP 地址更便于記憶,我們通常使用它來訪問網絡服務。

網絡應用客戶端想要跟服務端通信,必須先向 DNS 服務器查詢域名對應的 IP 地址。舉個例子,讀者訪問我的網站 fasionchan.com 時,瀏覽器需要先根據域名查詢網站的 IP 地址,再和網站的 Web 服務器進行通信。

那么,如何通過編程實現域名查詢呢?這是開發網絡應用無法回避的問題。

我們知道,DNS 服務器和客戶端之間使用 DNS 協議進行通信:客戶端先向服務器發送 請求報文 ,服務器將查詢結果封裝成 應答報文 ,回復客戶端。DNS 可以使用 UDP 或 TCP 作為傳輸層協議,通信端口號為 53 。

假設客戶端使用 UDP 協議,一次域名查詢的步驟大致如下:

  1. 創建一個 UDP 套接字;
  2. 封裝 DNS 請求報文,待查詢域名位于問題節;
  3. 通過 UDP 套接字,將請求報文發給 DNS 服務器(服務端端口一般是 53 );
  4. 等待服務端響應,并從 UDP 套接字讀取應答報文;
  5. 解析應答報文,獲得查詢結果;
  6. 關閉 UDP 套接字;

如果每個網絡應用都需要自行封裝 DNS 報文實現域名查詢,未免太麻煩了!為此,C庫提供了一系列工具函數。應用程序只需調用這些工具函數,即可完成域名查詢,不用自己操作套接字,或者封裝 DNS 報文。

示例程序

這個程序調用 C 庫函數 gethostbyname ,將用戶在命令行參數中指定的域名查詢出來:

  1. #include <arpa/inet.h> 
  2. #include <netdb.h> 
  3. #include <stdio.h> 
  4.  
  5. int main(int argc, char *argv[]) { 
  6.     if (argc != 2) { 
  7.         fprintf(stderr, "bad arguments"); 
  8.         return -1; 
  9.     } 
  10.  
  11.     char *name = argv[1]; 
  12.     printf("resolve domain name: %s\n"name); 
  13.  
  14.     struct hostent *result = gethostbyname(name); 
  15.     if (result == NULL) { 
  16.         if (h_errno == HOST_NOT_FOUND) { 
  17.             fprintf(stderr, "Hostname not found!\n"); 
  18.         } 
  19.  
  20.         if (h_errno == NO_DATA) { 
  21.             fprintf(stderr, "No such record\n"); 
  22.         } 
  23.  
  24.         if (h_errno == NO_RECOVERY) { 
  25.             fprintf(stderr, "\n"); 
  26.         } 
  27.  
  28.         if (h_errno == TRY_AGAIN) { 
  29.             fprintf(stderr, "Temporary error occurred, please try again!\n"); 
  30.         } 
  31.  
  32.         return -1; 
  33.     } 
  34.  
  35.     int i = 0; 
  36.     while (result->h_addr_list[i] != NULL) { 
  37.         printf("IP: %s\n", inet_ntoa(*(struct in_addr *)result->h_addr_list[i])); 
  38.         i++; 
  39.     } 
  40.  
  41.     return 0; 

顧名思義,gethostbyname 根據域名查詢主機的地址,結果一般是 IP 地址或者 IPv6 地址。

請看程序第 14 行,以待查詢域名為參數調用 gethostbyname 函數;它返回一個 hostent 結構體指針,結構體中保存著域名查詢結果。

第 15-33 行,檢查域名解析結果,空表示出錯;出錯時根據 h_errno 的值,分情況處理(詳情請見后文)。

第 35-39 行,從 hostent 結構體中取出查詢結果,并打印到屏幕上。

那么, gethostbyname 庫函數內部都做了些什么呢?答案其實不難猜到。它會幫我們創建 UDP 套接字、發送 DNS 請求報文、接收并解析應答報文。以這個程序為例,它的執行流(藍線)大致如下:

域名查詢庫函數

實際上,C 庫提供了一系列工具函數,用于域名查詢:

  • gethostbyname ,查詢指定域名,查詢結果保存在 hostent 結構體中,指針被返回給調用者;
  • gethostbyname_r ,同上,為線程安全版本,可在多線程環境中使用;
  • gethostbyname2 ,同一,但支持通過 af 參數指定查詢地址類型;
  • gethostbyname2_r ,同三,為線程安全版本,可在多線程環境中使用;

以 gethostbyname 為例,如果查詢成功,它將返回一個 hostent 結構體指針,結構體保存著查詢結果。如果查詢出錯,它將返回 NULL ,并將錯誤保存 h_errno 全局變量。一般而言,域名查詢出錯,可以分為這幾種情況:

HOST_NOT_FOUND ,表示指定主機不存在,即域名不存在;

NO_DATA ,表示域名存在其他記錄,但沒有地址相關記錄( A 或者 AAAA );

NO_RECOVERY ,域名服務器出現不可恢復錯誤;

TRY_AGAIN ,臨時出錯,可通過重試恢復;

當域名查詢失敗時,調用者必須檢查 h_errno 變量,分情況進行處理。

局限性

在網絡爬蟲、Socks5 代理等應用場景,域名查詢非常頻繁。這時直接使用 gethostbyname 系列庫函數,很有可能會面臨性能瓶頸。

一方面,gethostbyname 庫函數每次查詢域名時,都要創建一個 UDP 套接字來跟 DNS 服務器通信。這意味著,頻繁的域名查詢背后,必然伴隨著大量套接字的創建和銷毀,開銷可想而知!

另一方面,gethostbyname 庫函數將一直阻塞,直到 DNS 服務器返回結果或者查詢超時。這將嚴重制約系統的并發處理能力。

因此,在高頻查詢場景,不能直接使用 gethostbyname 等庫函數,必須采用一些經過優化的異步域名解析庫。

擴展閱讀

 

gethostbyname

 

責任編輯:武曉燕 來源: 小菜學編程
相關推薦

2023-12-28 10:30:56

類型系統Rust

2016-07-29 11:21:16

Ubuntulinux程序

2018-12-29 09:45:28

Linux編程語言命令

2009-06-08 21:35:02

Java啟動程序

2021-09-16 17:38:49

UbuntuLinuxJava

2021-09-13 09:01:02

Vue 技巧 開發工具

2014-05-28 09:45:55

CentOS域名服務器

2023-09-27 23:24:50

C++鏈表

2018-10-29 10:13:29

Windows 10應用程序卸載

2018-08-27 14:50:46

LinuxShellBash

2022-04-01 07:35:45

IDEAJavaWeb 項目

2019-03-27 13:20:31

Windows 10更新驅動程序

2010-05-20 17:52:02

2015-08-31 13:42:06

IDEDockerdoclipser

2020-08-28 07:00:00

WSLLinuxWindows 10

2021-08-30 07:50:42

腳本語言命令行

2018-06-05 08:51:04

Linux結束進程中止程序

2021-09-14 12:34:33

LinuxLinux終端

2024-08-13 08:27:24

PythonTCP協議網絡編程

2024-01-15 07:15:05

函數式編程代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美中文字幕在线 | 岛国一区 | 久久精品视频在线播放 | 在线国产一区二区 | www.男人天堂.com | 亚洲高清视频在线观看 | 免费久久视频 | 日韩五月天 | 噜噜噜色网 | 看a网站 | 一级做a爰片性色毛片16美国 | 欧美激情亚洲激情 | 草久在线 | 欧美一级特黄aaa大片在线观看 | 精品国产一区二区三区性色av | 色综合区| 国产精品免费一区二区三区四区 | 伊人精品一区二区三区 | 国产一区二区三区免费观看在线 | 日本在线小视频 | 国产亚洲精品综合一区 | 中文字字幕一区二区三区四区五区 | 日韩精品一区二区三区视频播放 | 婷婷开心激情综合五月天 | 一区二区高清在线观看 | 91久久久久久 | 久久国产精品久久久久 | 午夜精品久久久久久久久久久久久 | 国产乱码精品一区二区三区五月婷 | 国产一级片免费视频 | 国产精品国产a | 久久久久久亚洲精品 | 亚洲精品久久久一区二区三区 | 一区二区三区免费 | 国内久久 | 国产精品999 | 黄色免费观看网站 | 日韩高清三区 | 黄网站在线观看 | 九九九精品视频 | 激情五月综合 |