Linux下获取sockaddr的方法

本文介绍Unix系统中如何处理不同格式的套接字地址,包括两种主要方法:一是利用getaddrinfo函数获取地址信息;二是直接定义并初始化sockaddr_in结构。这两种方法均用于connect等函数中。

原址:http://blog.youkuaiyun.com/clearriver/article/details/4214744


在Unix下,为使不同格式的地址能够被传入到套接字函数,地址被强制转换成通用的sockaddr表示:

 struct sockaddr
{
     sa_family_t sa_family;
     char sa_data[];//长度由实现定义
     ......
};

在Linux下,定义为:

struct sockaddr
{
     sa_family_t sa_family;
     char sa_data[14];
     ......
};

因特网地址定义在<netinet/in.h>中,在IPV4中(AF_INET),套接字定义如下sockaddr_in:

struct n_addr
{
     in_addr_t  s_addr;//IPV4 addr
};
struct sockaddr_in
{
     sa_family_t sin_family;
     in_port_t sin_port;
     struct in_addr sin_addr;
};

有了以上定义,当我们需要使用socket地址时,比如connect函数:

connect(int sockfd, const struct sockaddr *serv_addr,socklen_t addrlen);

就需要得到struct sockaddr格式的socket地址。

目前从APUE和Unix/Linux编程实践看到两种获取的方法:

方法一(APUE):

通过调用函数getaddrinfo,在参数中返回struct addrinfo *类型链表,每个链节点中都包含了struct sockaddr类型成员,并将其用作为connect函数的参数。

其中struct addrinfo定义如下:

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

从自己程序拷过来的部分代码如下:

      struct addrinfo *ailist,*aip;
      struct addrinfo hint;
      int sockfd,err;
 
      hint.ai_flags = 0;
      hint.ai_family = 0;
      hint.ai_socktype = SOCK_STREAM;
      hint.ai_protocol = 0;
      hint.ai_addrlen = 0;
      hint.ai_canonname = NULL;
      hint.ai_addr = NULL;
      hint.ai_next = NULL;
      getaddrinfo(argv[1],"ruptime",&hint,&ailist);
      for(aip = ailist;aip != NULL;aip = aip->ai_next)
      {
            if((sockfd = socket(aip->ai_family,SOCK_STREAM,0))<0)
                 err = errno;
            if(connect_retry(sockfd,aip->ai_addr,aip->ai_addrlen)<0)
            {
                     err = errno;
            }
      }

方法二(Linux/Unix编程实践教程):

直接定义IPV4中socket 的地址格式sockaddr_in,然后调用函数gethostbyname,该函数返回struct hostent类型变量:

 struct hostent
 {
               char  *h_name;            /* official name of host */
               char **h_aliases;         /* alias list */
               int    h_addrtype;        /* host address type */
               int    h_length;          /* length of address */
               char **h_addr_list;       /* list of addresses */
   }

   #define h_addr h_addr_list[0] /* for backward compatibility */

然后对定义的sockaddr_in变量中的struct in_addr sin_addr进行初始化为h_addr,如下方式:

struct hostent   hp = gethostbyname("hostname");

struct sockaddr_in   saddr;

bcopy((void*)hp->h_addr,(void*)&saddr.sin_addr,hp->h_length);

 然后再对saddr中的其他成员进行赋值:

 saddr.sin_port = "8080";

 sassr.sin_family = AF_INET;

 最后将得到初始化完成的struct sockaddr_in通过强制转换为struct sockaddr来调用bind和connect等函数:

 bind(sock_id,(struct sockaddr *)&saddr,sizeof(saddr));

 在这种方法中,也可以通过调用函数inet_network()系列函数对saddr.sin_addr进行赋值:

 saddr.sin_addr.s_addr=inet_network("127.0.0.1");

 详细内容清参考关于这一系列函数的man手册。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值