威尼斯人棋牌:Beej’s Guide Network to Programming 系列

5.调用/捕获系统函数
       这部分我们使用系统的函数来访问网络他们在Unix的头文件里,以及任何支持套接字APP的操作系统(BSD、Windows、Linux、Mac等等)。当你调用他们中间的函数时,内核会自动帮助完成所有工作。

gethostbyname和gethostbyaddr这两个函数仅仅支持IPv4,getaddrinfo函数能够处理名字到地址以及服务到端口这两 种转换,返回的是一个sockaddr结构的链表而不是一个地址清单。这些sockaddr结构随后可由套接口函数直接使用。如此以 来,getaddrinfo函数把协议相关性安全隐藏在这个库函数内部。应用程序只要处理由getaddrinfo函数填写的套接口地址结构。该函数在 POSIX规范中定义了。

       大多数就卡在这些系统函数里。在这儿,因为你可能发现没有可用的man!好,为了帮助顺利适应它,我按照你的程序调用系统函数的顺序来讲解他们。

  1. addrinfo结构定义在头文件netdb.h中:
    struct addrinfo{
      int ai_flags; 
      int ai_family;                    //AF_INET、AF_INET6、UNIX etc 
      int ai_socktype;                //STREAM、DATAGRAM、RAW 
      int ai_protocol;                 //IPPROTO_IP、IPPROTO_IPV4、IPPROTO_IPV6 etc 
      size_t ai_addrlen;             //length of ai_addr 
      char* ai_canonname;        //full hostname 
      struct sockaddr* ai_addr;  //addr of host 
      struct addrinfo* ai_next;  
    };

       那么,你需要一些牛奶和饼干,再给你提供一些样例代码。其它的就是你的勇气、高昂的勇气!你会发现原来竟然是如此的快乐!

2.addrinfo结构

       (请注意,为了代码的简洁,没有包含错误检查。在调用getaddrinfo()函数成功时会返回一个有效的链表(linked list)。有些程序使用原始的地址(properly addressed ---也可译原型的地址)这也可以。)

结构

5.1. getaddrinfo()---准备运行
       这个是真正的默默无闻的函数,虽然它有没多参数,但是实际用起来很简单。它对于你建立一个地址结构起到了简化的作用。

固定的参数

       一个小小的历史:它曾经是,你会使用所谓的gethostbyname ()的函数做DNS查找。然后你手工加载一些信息给结构SOCKADDR_IN ,并供你调用。

typedef struct addrinfo {

       值得庆幸的是,这不再是必要的了。(如果你要编写工作在IPv4和IPv6的代码,使用上边所说的,也是不可取的!)在这现代化的时代,你已经有了getaddrinfo()函数并为你封装好了不少东西,其中包括DNS和服务名称查找,除了你自己填写所需要的结构!

int    ai_flags;

       让我们一起来看看!

int    ai_family;

#include<sys/types.h>

int    ai_socktype;

#include<sys/socket.h>

int             ai_protocol;

#include<netdb.h>

size_t                       ai_addrlen;

 

char                      * ai_canonname;

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

struct sockaddr     * ai_addr;

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

struct addrinfo      * ai_next;}

const struct addrinfo *hints,

ai_addrlen must be zero or a null pointer

struct addrinfo **res);

ai_canonname must be zero or a null pointer

       在这个函数里有3个输入参数和1个作为返回值的指向链表的指针res。

ai_addr must be zero or a null pointer

       入参node是要连接的主机名或者IP地址。

ai_next must be zero or a null pointer

       下一个入参service是端口号,比如“80”,或者其它特定的服务名称像“http”

可以改动的参数

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

ai_flags:            AI_PASSIVE,AI_CANONNAME,AI_NUMERICHOST

       最后,入参hints指向一个你已经填写好了的addrinfo结构。

ai_family:           AF_INET,AF_INET6

       下面的示例是服务器在你的主机IP地址和端口号3490监听。请注意,他们没有做任何实际的监听或者网络设置;它只是在设置了结构hints并且做了调用。

ai_socktype:     SOCK_STREAM,SOCK_DGRAM

 

ai_protocol:       IPPROTO_IP, IPPROTO_IPV4, IPPROTO_IPV6 etc.

int status;

3 参数说明

struct addrinfohints;

在getaddrinfo函数之前通常需要对以下6个参数进行以下设置:nodename、servname、

struct addrinfo*servinfo;            // will point to theresults

hints ai_flags、ai_family、ai_socktype、ai_protocol

 

在6项参数中,对函数影响最大的是nodename,sername和hints.ai_flag

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

而ai_family只是有地址为IPv4地址或IPv6地址的区别。而ai_protocol一般是为0不作改动。

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

其中ai_flags、ai_family、ai_socktype说明如下:

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: %sn”,gai_strerror(status));

ai_family

       exit(1);

AF_INET

}

2

 

IPv4

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

AF_INET6

 

23

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

IPv6

 

AF_UNSPEC

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

0

 

协议无关

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

ai_protocol

 

IPPROTO_IP

       请注意:因为ai_family设置为AF_UNSPEC所以达到了与版本无关。你也能设置专为IPv4或者IPv6工作以及其它的地址族。

0

       此外你在这儿看到了AI_PASSIVE标志;他告诉getaddrinfo()复制本机地址给套接字结构。这很好,因为没有硬编码。

IP协议

       译者注:上边的情况通常使用在服务器端!

IPPROTO_IPV4

                     下边说的就是客户端的情况。

4

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

IPv4

int status;

IPPROTO_IPV6

struct addrinfohints;

41

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

IPv6

 

IPPROTO_UDP

本文由威尼斯人棋牌发布于计算机教程,转载请注明出处:威尼斯人棋牌:Beej’s Guide Network to Programming 系列