【Linux C | 網絡編程】getaddrinfo 函數詳解及C語言例子

😁博客主頁😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客內容🤑:🍭嵌入式開發、Linux、C語言、C++、數據結構、音視頻🍭
🤣本文內容🤣:🍭介紹 getaddrinfo 函數 🍭
😎金句分享😎:🍭你不能選擇最好的,但最好的會來選擇你——泰戈爾🍭
?發布時間?:2024-03-01 14:15:54

本文未經允許,不得轉發!!!

目錄

  • 🎄一、概述
  • 🎄二、getaddrinfo 函數
    • ?2.1 getaddrinfo 函數介紹
    • ?2.2 struct addrinfo 結構體說明
  • 🎄三、gai_strerror、freeaddrinfo 函數
    • ?3.1 gai_strerror 函數介紹
    • ?3.2 freeaddrinfo 函數介紹
  • 🎄四、getaddrinfo 函數使用例子
  • 🎄五、總結


在這里插入圖片描述

🎄一、概述

前面介紹過域名和IP地址之間轉換的兩個函數:gethostbynamegethostbyaddr,但是這兩個函數僅僅支持IPv4。本文再介紹一個可支持 IPv4 和 IPv6 的函數getaddrinfo,該函數可以處理名字到地址以及服務到端口這兩種轉換。


在這里插入圖片描述

🎄二、getaddrinfo 函數

?2.1 getaddrinfo 函數介紹

  • 1、函數原型:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    int getaddrinfo(const char *node, const char *service,const struct addrinfo *hints, struct addrinfo **res);
    void freeaddrinfo(struct addrinfo *res);
    const char *gai_strerror(int errcode);
    
  • 2、函數描述:
    getaddrinfo函數根據給定的主機名和服務名,返回一個struct addrinfo結構鏈表,每個struct addrinfo結構都包含一個互聯網地址。getaddrinfo函數將gethostbynamegetservbyname函數提供的功能組合到一個接口中,但與后一個函數不同,getaddrinfo是可重入的,可支持IPv4、IPv6。

  • 3、函數參數:

    • node:一個主機名或地址串( IPv4的點分十進制數串或IPv6的十六進制數串)。如果hints.ai_flags包含AI_NUMERICHOST標志,則此參數必須是IP地址字符串;

    • service:一個服務名或十進制端口號數串。如果此參數被設置為一個服務名稱,則會將其轉換為相應的端口號。如果設置為NULL,則返回的套接字地址的端口號將保持未初始化狀態。如果在hints.ai_flags中指定了AI_NUMERICSERV,并且此參數不為NULL,則此參數必須指向包含數字端口號的字符串;

    • hints:hints參數可以是一個空指針,也可以是一個指向某個addrinfo結構的指針,調用者在這個結構中填入關于期望返回的信息類型的暗示。hints參數中,調用者可以設置的字段有:ai_flags、ai_family、ai_socktype、ai_protocol。其中,ai_flags取值如下表:

      取值說明
      AI_PASSIVE套接字將用于被動打開.
      AI_CANONNAME告知getaddrinfo函數返回主機的規范名字.
      AI_NUMERICHOST防止任何類型的名字到地址映射,hostname參數必須是一個地址串。
      AI_NUMERICSERV防止任何類型的名字到服務映射, service參數必須是一個十進制端口號。AI__V4MAPPED
      AI_V4MAPPED如果同時指定ai_family成員的值為AF_INET6,那么如果沒有可用的AAAA記錄,就返回與A記錄對應的IPv4映射的IPv6地址。
      AI_ALL如果同時指定AI_V4MAPPED標志,那么除了返回與AAAA記錄對應的IPv6地址外,還返回與A記錄對應的IPv4映射的IPv6地址。
      AI_ADDRCONFIG按照所在主機的配置選擇返回地址類型,也就是只查找與所在主機回饋接口以外的網絡接口配置的IP地址版本一致的地址。

      ai_family 取值一般為AF_XXX,例如:AF_INETAF_INET6AF_UNSPEC(不限制IP地址協議);
      ai_socktype 取值一般為SOCK_XXX,例如:SOCK_STREAMSOCK_DGRAM
      ai_protocol 字段指定返回的套接字地址的協議。在該字段中指定0表示getaddrinfo函數可以返回具有任何協議的套接字地址。

    • res:傳出參數,如果本函數返回成功0,則 res 參數指向的變量已被填入一個指針,它指向的是由其中的 ai_next 成員串接起來的 addrinfo 結構鏈表。

  • 4、返回值:
    成功返回0,失敗返回非0,取值如下表:

    常值說明
    EAI_AGAIN名字解析中臨時失敗
    EAI_BADFLAGSai_flags的值無效
    EAI_FAIL名字解析中不可恢復地失敗
    EAI_FAMILY不支持ai_family
    EAI_MEMORY內存分配失敗
    EAI_NONAMEhostname或service未提供,或者不可知
    EAI_OVERFTOW用戶參數緩沖區溢出(僅限getnameinfo( )函數)
    EAI_SERVICE不支持ai_socktype類型的service
    EAI_SOCKTYPE不支持ai_socktype
    EAI_SYSTEM在errno變量中有系統錯誤返回

?2.2 struct addrinfo 結構體說明

struct addrinfo結構體定義在頭文件 netdb.h 中,結構體聲明如下:

struct addrinfo {int              ai_flags;int              ai_family;int              ai_socktype;int              ai_protocol;socklen_t        ai_addrlen;struct sockaddr *ai_addr;char            *ai_canonname;struct addrinfo *ai_next;
};

在這里插入圖片描述
結構體字段說明:

  • ai_flags:標志,在調用時使用,具體取值見上面 hints參數 的說明;
  • ai_family:IP協議族,一般取值有AF_INETAF_INET6AF_UNSPEC(不限制IP地址協議);
  • ai_socktype:socket類型,取值一般為SOCK_XXX,例如:SOCK_STREAMSOCK_DGRAM
  • ai_protocol:此字段指定返回的套接字地址的協議,一般有IPPROTO_UDPIPPROTO_TCP
  • ai_addrlen:返回的地址結構體ai_addr的長度。一般IPv4是4,IPv6是16;
  • ai_addr:存儲IP地址數據,一般轉換成struct sockaddr_instruct sockaddr_in6使用;
  • ai_canonname:正式的、標準的名稱;
  • ai_next:用作鏈表結點指針,指向下一個struct addrinfo結點。

在這里插入圖片描述

🎄三、gai_strerror、freeaddrinfo 函數

在使用 getaddrinfo 函數時,還有兩個函數也會使用到,下面簡單介紹一下這兩個函數。

?3.1 gai_strerror 函數介紹

  • 1、函數原型:
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    const char *gai_strerror(int errcode);
    
  • 2、函數描述:
    getaddrinfo出錯會返回的非0錯誤值,gai_strerror以這些值為它的唯一參數,返回一個指向對應的出錯信息串的指針。
    常值說明
    EAI_AGAIN名字解析中臨時失敗
    EAI_BADFLAGSai_flags的值無效
    EAI_FAIL名字解析中不可恢復地失敗
    EAI_FAMILY不支持ai_family
    EAI_MEMORY內存分配失敗
    EAI_NONAMEhostname或service未提供,或者不可知
    EAI_OVERFTOW用戶參數緩沖區溢出(僅限getnameinfo( )函數)
    EAI_SERVICE不支持ai_socktype類型的service
    EAI_SOCKTYPE不支持ai_socktype
    EAI_SYSTEM在errno變量中有系統錯誤返回

?3.2 freeaddrinfo 函數介紹

  • 1、函數原型:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    void freeaddrinfo(struct addrinfo *res);
    
  • 2、函數描述:
    由getaddrinfo返回的所有存儲空間都是動態獲取的(譬如來自malloc調用),包括addrinfo結構、ai_addr結構和ai_canonname字符串。這些存儲空間需要通過調用freeaddrinfo返還給系統。

  • 3、參數
    res:res參數應指向由getaddrinfo返回的第一個addrinfo結構。這個鏈表中的所有結構以及由它們指向的任何動態存儲空間(譬如套接字地址結構和規范主機名)都被釋放掉。

  • 4、注意:
    如果getaddrinfo成功返回后,我們為了保存返回的信息而僅僅復制了返回的addrinfo結構,在調用freeaddrinfo后,就會存在一個錯誤:我們前面復制的addrinfo結構中的指針指向的內存空間已在調用freeaddrinfo后返還給系統。
    這種只復制結構體而沒復制結構體字段指向的內容的方式稱為淺復制;復制結構體又復制結構體字段指向的內容的方式稱為深復制。上面例子中,如果確實要保存信息,可以使用深復制來保存。


在這里插入圖片描述

🎄四、getaddrinfo 函數使用例子

// getaddrinfo_sample.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>int main(int argc, char *argv[]) {struct addrinfo hints, *result, *rp;// 定義addrinfo結構體變量int err;                         	// getaddrinfo函數返回值char ipstr[INET6_ADDRSTRLEN];       // 存儲IP地址字符串的緩沖區if (argc != 2) {                    // 檢查命令行參數數量是否正確fprintf(stderr, "Usage: %s hostname\n", argv[0]);return -1;}memset(&hints, 0, sizeof(hints));  	// 初始化hints結構體hints.ai_family = AF_UNSPEC;		// 不限制IP地址版本hints.ai_socktype = SOCK_STREAM;	// 使用TCP協議if ((err = getaddrinfo(argv[1], NULL, &hints, &result)) != 0) {  // 解析主機名并將結果存儲在result指針中fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(err));return -1;}printf("IP addresses for %s:\n", argv[1]);for (rp = result; rp != NULL; rp = rp->ai_next) {	// 遍歷result指針中的所有套接字地址結構void *addr;char *ipver;if (rp->ai_family == AF_INET) {	// IPv4地址struct sockaddr_in *ipv4 = (struct sockaddr_in *)rp->ai_addr;addr = &(ipv4->sin_addr);ipver = "IPv4";} else { 						// IPv6地址struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)rp->ai_addr;addr = &(ipv6->sin6_addr);ipver = "IPv6";}inet_ntop(rp->ai_family, addr, ipstr, sizeof(ipstr));  // 將套接字地址結構轉換為IP地址字符串printf("  %s: %s\n", ipver, ipstr);                    // 打印IP地址和版本號}freeaddrinfo(result);   // 釋放由getaddrinfo函數分配的內存return 0;    // 程序正常退出
}

運行結果:
下面是分別查詢www.baidu.com(百度)、www.goolge.com(谷歌)、blog.csdn.net(CSDN)、localhost(本地主機名)、ip6-localhostip6-localnet的打印結果。
在這里插入圖片描述

localhost(本地主機名)、ip6-localhostip6-localnet,這三個在/etc/hosts文件中有說明,可以發現與查詢的一致。
在這里插入圖片描述


在這里插入圖片描述

🎄五、總結

👉本文重點介紹了 getaddrinfo、freeaddrinfo、gai_strerror 三個函數,并給出C語言使用例子。

通過本文的介紹,我們深入探討了 Linux 系統中 getaddrinfo 函數的定義和使用場景。getaddrinfo 函數在網絡編程中扮演著重要角色,允許開發人員根據主機名和服務名動態獲取地址信息,為構建靈活且健壯的網絡應用提供了便利。希望本文能幫助您更好地了解并應用 getaddrinfo 函數。

在這里插入圖片描述
如果文章有幫助的話,點贊👍、收藏?,支持一波,謝謝 😁😁😁

參考資料:
1、Linux的man手冊
2、《Unix網絡編程卷1》

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/711953.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/711953.shtml
英文地址,請注明出處:http://en.pswp.cn/news/711953.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

element-plus 的el-img組件訪問oss圖片自動拼接前端地址

這是我的組件代碼 <el-image style"width: 100px; height: 100px" :src"scope.row.logo" />訪問時候 竟然憑借上了前端的地址端口 原來是我的oss服務是使用了域名做cdn加速的 內容分發網絡&#xff08;CDN&#xff09;或者服務器配置&#xff0c;可…

k8s學習-數據管理之nfs手動搭建

需要先準備好3臺虛擬機 系統CentOS7 IP 192.168.200.128 master IP 192.168.200.129 node1 IP 192.168.200.130 node2 問題描述 在學習數據管理的時候創建完pv和pvc以后&#xff0c;創建了pod使用pvc&#xff0c;但是pod創建不成功。 查看pod描述 kubectl describe pod myp…

安全防御(第六次作業)

攻擊可能只是一個點&#xff0c; 防御需要全方面進行 IAE引擎 DFI和DPI技術 --- 深度檢測技術 DPI --- 深度包檢測技術 --- 主要針對完整的數據包&#xff08;數據包分片&#xff0c;分段需要重組&#xff09; &#xff0c;之后對 數據包的內容進行識別。&#xff08;應用層&a…

【湖南省建筑類中級職稱申報攻略】企業專場條件寬松,不費勁拿證書!

【湖南省建筑類中級職稱申報攻略】企業專場條件寬松&#xff0c;不費勁拿證書&#xff01; 2024年湖南省電力電氣工程師申報評審/企業專場不費勁 湖南省建筑類中級職稱申報評審都是以考代評&#xff0c;符合條件參加考試&#xff0c;考試合格了&#xff0c;職稱申報審核通過就…

c語言經典測試題8

在c語言經典測試題6的第一題&#xff0c;大家是否想過可不可以將遞歸參數改為s呢&#xff1f;或許有的人已經試過了&#xff0c;但是發現好像不會有結果&#xff0c;其實是因為s為后置&#xff0c;先試用后加1&#xff0c;然而我們這個是在s出了函數之后才會運行加1操作&#x…

CentOS 7開啟Web服務

之前有寫過用kali開啟web服務方法&#xff0c;這次寫個用cendos7開啟服務的步驟&#xff01; 1、安裝httpd yum install -y httpd 若顯示安裝失敗&#xff0c;報錯原因為找不到httpd的安裝包&#xff0c;可參考這篇文件更新yum源&#xff1a;CentOS 7更換yum源|詳細步驟-CSDN…

CDN CloudFlare 接入 OCI 對象存儲

在當今數字化時代&#xff0c;網站性能和可用性是業務成功的關鍵。為了提供快速且可靠的訪問體驗&#xff0c;許多組織正在尋找有效的內容分發網絡&#xff08;CDN&#xff09;解決方案。CloudFlare作為業界領先的CDN提供商&#xff0c;其強大的全球網絡基礎設施能夠加速網站內…

獲取秒值, 把秒值轉換為時分秒, 及把時分秒轉換成秒值代碼

// author: hjjdebug // date: 2024年 03月 01日 星期五 15:29:32 CST // description: 獲取秒值, 把秒值轉換為時分秒, 及把時分秒轉換成秒值 // 使用就這么簡單. // 有時候程序輸出需要打印時間信息, 就可以這么干了. /// #include <stdio.h> #include <time.h> …

tvm編譯爬坑,包括rpc

環境 docker ubuntu20.04 主要參考&#xff1a; TVM的安裝編譯 - 知乎 其他還參考&#xff1a; https://www.cnblogs.com/whiteBear/p/16629669.html 用TVM在Android上部署模型 (II. Docker安裝TVM環境) - 知乎 對 APK 進行手動簽名 - Xamarin | Microsoft Learn Android …

《PyTorch深度學習實踐》第十二講循環神經網絡基礎

一、RNN簡介 1、RNN網絡最大的特點就是可以處理序列特征&#xff0c;就是我們的一組動態特征。比如&#xff0c;我們可以通過將前三天每天的特征&#xff08;是否下雨&#xff0c;是否有太陽等&#xff09;輸入到網絡&#xff0c;從而來預測第四天的天氣。 我們可以看RN…

Python實現雙向鏈表:從基礎到應用

一、引言 雙向鏈表是一種比單向鏈表更復雜的數據結構&#xff0c;每個節點除了包含數據和指向下一個節點的指針外&#xff0c;還包含一個指向前一個節點的指針。這種結構使得我們可以從鏈表的任何節點開始&#xff0c;向前或向后遍歷鏈表。 目錄 一、引言 二、節點定義 三、…

OPPO打響AI手機第一槍

明敏 發自 凹非寺 量子位 | 公眾號 QbitAI 2024開年&#xff0c;AI趨勢依舊高歌猛進。 一邊&#xff0c;Sora爆火成為現象級AIGC應用&#xff0c;帶動AI再度成為春節后全民熱議的第一話題。另一邊&#xff0c;手機廠商開始大舉All in AI&#xff0c;“放棄傳統智能手機”、“…

【Qt】Sqlite數據庫加密

1. 加密方式 對數據庫文件加密。既不會暴露表結構&#xff0c;也不會暴露數據細節。 2. 加密工具&#xff08;QtCipherSqlitePlugin&#xff09; 用于密碼 SQLite 的 Qt 插件&#xff0c;它基于 SQLite 源和 wxWidget 中的 wxSQLite3插件github地址&#xff1a;https://gith…

gpt-3.5-turbo與星火認知大模型v3.5回答對比

創建kernel // Create a kernel with OpenAI chat completionKernel kernel Kernel.CreateBuilder().AddOpenAIChatCompletion(modelId:"使用的模型id" ,apiKey: "APIKey").Build();使用訊飛星火認知大模型的話&#xff0c;可以參考我這一篇文章&#xff…

突破編程_C++_高級教程(正則表達式)

1 正則表達式的概念 正則表達式&#xff0c;又稱規則表達式&#xff0c;&#xff08;Regular Expression&#xff0c;在代碼中常簡寫為 regex 、regexp 或 RE&#xff09;&#xff0c;是一種文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a 到 z 之間的字母&a…

c++函數指針 回調函數

目錄 函數指針 ?編輯 實例 函數指針作為某個函數的參數 實例 std::function輕松實現回調函數 綁定一個函數 作為回調函數 作為函數入參 函數指針 函數指針是指向函數的指針變量。 通常我們說的指針變量是指向一個整型、字符型或數組等變量&#xff0c;而函數指針是指向…

證券相關業務知識

證券相關業務知識 LOF交易回售業務觸發條件 股票代碼區分融券專戶競價交易與大宗交易一級市場和二級市場ETF交易融資融券交易&#xff08;兩融&#xff09;融券強平轉托管簿記和預簿記期權權證股票板塊 LOF交易 LOF&#xff0c;即上市型開放式基金&#xff08;Listed Open-End…

【Java】UWB高精度工業定位系統項目源代碼

目錄 UWB技術原理 優勢 1. 高精度&#xff1a; 2. 抗干擾能力強&#xff1a; 3. 定位范圍廣&#xff1a; 4. 實時性強&#xff1a; 應用前景 定位系統源碼功能介紹 實時定位&#xff1a; 軌跡回放&#xff1a; 區域管理&#xff1a; 巡檢管理: 數據可視化分析&…

BAT等大廠必問技術面試題,2024Android開發面試解答之設計模式

IT行業薪水高&#xff0c;這是眾所周知的&#xff0c;所以很多人大學都選擇IT相關專業&#xff0c;即使非該專業的人&#xff0c;畢業了也想去一個培訓機構鍍鍍金&#xff0c;進入這一行業。 但是有關這個行業35歲就退休的說法&#xff0c;也一直盛傳。 加上這幾年不斷有各大…

回溯 Leetcode 47 全排列II

全排列II 給定一個可包含重復數字的序列 nums &#xff0c;按任意順序 返回所有不重復的全排列。 Leetcode 47 學習記錄自代碼隨想錄 示例 1&#xff1a; 輸入&#xff1a;nums [1,1,2] 輸出&#xff1a; [[1,1,2], [1,2,1], [2,1,1]] 示例 2&#xff1a; 輸入&#xff1…