程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> Beej’s Guide Network to Programming 系列連載08

Beej’s Guide Network to Programming 系列連載08

編輯:關於C

5.調用/捕獲系統函數
       這部分我們使用系統的函數來訪問網絡他們在Unix的頭文件裡,以及任何支持套接字APP的操作系統(BSD、Windows、Linux、Mac等等)。當你調用他們中間的函數時,內核會自動幫助完成所有工作。

       大多數就卡在這些系統函數裡。在這兒,因為你可能發現沒有可用的man!好,為了幫助順利適應它,我按照你的程序調用系統函數的順序來講解他們。

       那麼,你需要一些牛奶和餅干,再給你提供一些樣例代碼。其它的就是你的勇氣、高昂的勇氣!你會發現原來竟然是如此的快樂!

       (請注意,為了代碼的簡潔,沒有包含錯誤檢查。在調用getaddrinfo()函數成功時會返回一個有效的鏈表(linked list)。有些程序使用原始的地址(properly addressed ---也可譯原型的地址)這也可以。)

5.1. getaddrinfo()---准備運行
       這個是真正的默默無聞的函數,雖然它有沒多參數,但是實際用起來很簡單。它對於你建立一個地址結構起到了簡化的作用。

       一個小小的歷史:它曾經是,你會使用所謂的gethostbyname ()的函數做DNS查找。然後你手工加載一些信息給結構SOCKADDR_IN ,並供你調用。

       值得慶幸的是,這不再是必要的了。(如果你要編寫工作在IPv4和IPv6的代碼,使用上邊所說的,也是不可取的!)在這現代化的時代,你已經有了getaddrinfo()函數並為你封裝好了不少東西,其中包括DNS和服務名稱查找,除了你自己填寫所需要的結構!

       讓我們一起來看看!

#include<sys/types.h>

#include<sys/socket.h>

#include<netdb.h>

 

intgetaddrinfo(const char *node,                    //e.g.  www.example.comor IP

const char *service,              //e.g.  “http” or port number

const struct addrinfo *hints,

struct addrinfo **res);

       在這個函數裡有3個輸入參數和1個作為返回值的指向鏈表的指針res。

       入參node是要連接的主機名或者IP地址。

       下一個入參service是端口號,比如“80”,或者其它特定的服務名稱像“http”

、“ftp”、“telnet”、“smtp”等等。

       最後,入參hints指向一個你已經填寫好了的addrinfo結構。

       下面的示例是服務器在你的主機IP地址和端口號3490監聽。請注意,他們沒有做任何實際的監聽或者網絡設置;它只是在設置了結構hints並且做了調用。

 

int status;

struct addrinfohints;

struct addrinfo*servinfo;            // will point to theresults

 

memset(&hints,0, sizeof(hints));        // make sure thestruct is empty

hints.ai_family =AF_UNSPEC;        // don’t care IPv4 orIPv6

hints.ai_socktype= SOCK_STREAM;   // TCP stream sockets

hints.ai_flags =AI_PASSIVE;                  // fill in myIP for me

 

if ((status =getaddreinfo(NULL, “3049”,&hints, &servinfo)) != 0) {

       fprintf(stderr, “getaddrinfo error: %s\n”,gai_strerror(status));

       exit(1);

}

 

// servinfo nowpoints to a linked list of 1 or more struct addrinfos

 

// … do everythinguntil you don’t need servinfo anymore …

 

// … do everythinguntil you don’t need servinfo anymore …

 

freeaddrinfo(servinfo);// free the linked-list

 

       請注意:因為ai_family設置為AF_UNSPEC所以達到了與版本無關。你也能設置專為IPv4或者IPv6工作以及其它的地址族。

       此外你在這兒看到了AI_PASSIVE標志;他告訴getaddrinfo()復制本機地址給套接字結構。這很好,因為沒有硬編碼。

       譯者注:上邊的情況通常使用在服務器端!

                     下邊說的就是客戶端的情況。

       示例:連接到www.example.net的3049端口。

int status;

struct addrinfohints;

struct addrinfo *servinfo;            // will point to the results

 

memset(&hints,0 sizeof(hints));  // make sure the structis empty

hints.ai_family =AF_UNSPEC; // don’t care IPv4 or IPv6

hints.ai_socktype= SOCK_STREAM;   // TCP stream sockets

 

// get ready toconnect

status =getaddrinfo(www.example.net, “3049”, &hints, &servinfo);

 

// servinfo nowpoints to a linked list of 1 or more struct addrinfos

 

// etc.

 

       我一直說servinfo是一個可以指向各種地址的指針。我們寫一個簡單的演示程序來顯示不同的地址信息。這個程序在命令行上打印出你指定主機的IP地址。

showip.c

所需頭文件列表:

#include<stdio.h>

#include<string.h>

#include<sys/types.h>

#include<sys/socket.h>

#include<netdb.h>

#include<arpa/inet.h>

 流程圖

\
 

正如您所看到的,代碼調用的getaddrinfo()來填寫由res指向的鏈表,然後我們可以遍歷列表以及打印在命令行上。

譯者注:測試IPv6失敗!請讀者自行查找國內可用的IPv6站點。

 

       現在我們已經在控制之下,我們將使用getaddrinfo()得到的結果,我們要傳遞給其他socket函數,終於,建立我們的網絡連接!請繼續閱讀!

 

摘自 xiaobin_HLJ80的專欄
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved