socket地址说明及转换函数

来源:互联网 发布:婚纱胸贴哪种好用 知乎 编辑:程序博客网 时间:2024/06/05 08:49

1.   三种常见结构类型

  在套接字编程编程中,有三种常见的结构类型,它们用来存放socket地址信息。这三种结构类型分别为struct in_addr、struct sockaddr、struct sockaddr_in,对这三种结构类型说明如下。

struct in_addr专门用来存储IP地址,对于IPv4来说,IP地址为32位无符号整数。其定义如下:

struct in_addr {

unsigned long s_addr;

};

struct sockaddr结构用来保存套接字地址信息,其定义如下:

struct sockaddr {

unsigned short sa_family; /* 地址族, AF_xxx */

char sa_data[14]; /* 14字节的协议地址*/

};

struct sockaddr结构中sa_family成员说明的是地址族类型,一般为“AF_INET”;而sa_data则包含远程主机的IP地址和端口等信息。

struct sockaddr结构类型使用在socket的相关系统调用函数中,但这个结构sa_data字段可以包含较多信息,不利于方便编程和对其进行赋值,因此建立了struct sockaddr_in结构,该结构与struct sockaddr结构大小相等,能更好处理struct sockaddr结构中的数据。对struct sockaddr_in结构变量进行赋值完成后,在进行socket相关系统调用时,再将struct sockaddr_in结构变量强制转换为struct sockaddr结构类型。

struct sockaddr_in结构定义如下:

struct sockaddr_in {  /*“in” 代表“Internet”*/

short int sin_family; /* Internet地址族*/

unsigned short int sin_port; /* 端口号*/

struct in_addr sin_addr; /* Internet地址*/

unsigned char sin_zero[8]; /* 填充0(为了保持和struct sockaddr一样大小)*/

};

在实际应用编程中,对套接字地址结构使用方法和流程如下:

①    首先,定义一个sockaddr_in结构变量,并将它初始化为0,代码如下:

struct sockaddr_in myad;

memset(&myad,0,sizeof(struct sockaddr_in));

②    然后,给这个结构变量赋值,代码如下:

myad.sin_family=AF_INET;

myad.sin_port=htons(8080);

myad.sin_addr.s_addr=htonl(INADDR_ANY);

③    在进行函数调用时,将这个结构强制转换为struct sockaddr类型,代码如下:

bind(serverFd, (struct sockaddr *)& myad, sizeof(myad))

2.   整型字节序转换函数

为保证“大端”和“小端”字节序的机器之间能相互通信,需在发送多字节整数时,将主机字节序转换成网络字节序,或将网络字节序转换为主机字节序。下图说明了网络字节序与小端字节序、大端字节序的对照关系。字节转换主要是针对整型进行转换,字符型由于是单字节,所以不存在这个问题。整型字节序转换函数函数原型及其说明如下表所示。

 

所需头文件

#include <netinet/in.h>

函数说明

完成网络字节序与主机字节序的转换

函数原型

uint16_t  htons(uint16_t hostshort) /*短整型主机转换为网络字节序*/

uint32_t  htonl(uint32_t hostlong) /*长整型主机转换为网络字节序*/                         

uint16_t  ntohs(uint16_t netshort) /*短整型网络转换为主机字节序*/

uint32_t  ntohl(uint32_t netlong)  /*长整型网络转换为主机字节序*/

函数传入值

hostshort、hostlong:为转换前主机字节序数值

netshort、netlong:为转换前网络字节序数值

函数返回值

①     htons、htonl返回转换后网络字节序数值

②     ntohs、ntohl返回转换后主机字节序数值

附加说明

h表示主机,n表示网络,s表示短整数,l表示长整数,to表示转换

3.   IP地址转换函数

IP地址转换函数是指完成点分十进制IP地址与二进制IP地址之间的相互转换。IP地址转换主要有inet_aton、inet_addr和inet_ntoa这三个函数完成,这三个地址转换函数都只能处理IPv4地址,而不能处理IPv6地址。这三个函数的函数原型及其具体说明如下列表格所示。

 

inet_addr(将点分十进制IP地址转换为二进制地址)

所需头文件

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

函数说明

将点分十进制IP地址转换为二进制地址

函数原型

in_addr_t inet_addr(const char *cp)

函数传入值

cp:点分十进制IP地址,如“10.10.10.1”

函数返回值

成功:返回二进制形式的IP地址

失败:返回一个常值INADDR_NONE(32位均为1)

 

inet_aton(将点分十进制IP地址转换为二进制地址)

所需头文件

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

函数说明

将点分十进制IP地址转换为二进制地址

函数原型

int inet_aton(const char *cp, struct in_addr *inp)

函数传入值

cp:点分十进制IP地址,如“10.10.10.1”

函数传出值

inp:转换后二进制地址信息保存在inp中

函数返回值

成功:非0

失败:0

 

inet_ntoa(将二进制地址转换为点分十进制IP地址)

所需头文件

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

函数说明

将二进制地址转换为点分十进制IP地址

函数原型

char *inet_ntoa(struct in_addr in)

函数传入值

in:二进制IP地址

函数返回值

成功:返回字符串指针,此指针指向了转换后的点分十进制IP地址

失败:NULL

 

4.   获取主机信息函数

(1)getpeername函数原型

getpeername(获取通信对方信息)

所需头文件

#include <netinet/in.h>

函数说明

获取通信对方信息

函数原型

int getpeername(int s, struct sockaddr *name, socklen_t *namelen)

函数传入值

s:所连接的socket文件描述符

namelen:返回name的长度,可以设置为sizeof(struct sockaddr)

函数传出值

name:指向包含对方IP地址、端口等信息的sockaddr结构地址

函数返回值

成功

0

失败

-1,失败原因存于error中

 

(2)gethostname函数原型

gethostname(获取主机名称)

所需头文件

#include <netinet/in.h>

函数说明

获取通信对方信息

函数原型

int gethostname(char *name, size_t len)

函数传入值

len:name数组的长度

函数传出值

name:主机的名称

函数返回值

成功

0

失败

-1,失败原因存于error中

 

(3)gethostname函数举例

gethostname.c源代码如下:

#include <stdio.h>

#include <string.h>

#include <unistd.h>

int main()

{

    char hostname[30] ;

    int flag =0 ;

    memset(hostname, 0x00, sizeof(hostname));

    flag = gethostname(hostname, sizeof(hostname));

    if( flag <0 )

    {

        perror("gethostname error") ;

        return -1 ;

    }

    printf( "hostname = %s\n", hostname) ;

    return 0 ;

}

编译  gcc gethostname.c -o gethostname。

执行  ./gethostname,执行结果如下:

hostname = ubuntu

 

(4)通过主机名或域名获取IP地址  

gethostbyname(通过主机名或域名获取网络信息)

所需头文件

#include <netinet/in.h>

函数说明

gethostbyname会返回一个hostent结构指针,该结构具体说明如下:

struct hostent {

   char *h_name;         /*正式的主机名称*/

   char **h_aliases;     /*该主机的其他别名*/

   int h_addrtype;       /*地址类型,通常是AF_INET*/

   int h_length;         /*地址的长度*/

   char **h_addr_list;   /*该主机的所有地址*/

   };

函数原型

struct hostent *gethostbyname(const char *name)

函数传入值

name:域名或主机名

函数传出值

name:主机的名称

函数返回值

成功: 返回hostent指针

失败:NULL,失败原因存于h_error中(注意错误原因不存于error中)

附加说明

该函数首先在/etc/hosts文件中查找是否有匹配的主机名。如果没有,则根据在域名解析配置文件

 

(5)gethostbyname函数举例

gethostbyname.c源代码如下:

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <netdb.h>

#include <sys/types.h>

#include <netinet/in.h>

int main(int argc, char *argv[])

{

    struct hostent *h;

    if (argc != 2) {  /* error check the command line */

        fprintf(stderr,"usage: getip address\n");

        return -1;

    }

    if ((h=gethostbyname(argv[1])) == NULL) {  /* get the host info */

        herror("gethostbyname");

        return -1;

    }

    printf("Host name  : %s\n", h->h_name);

    printf("IP Address : %s\n",inet_ntoa(*((struct in_addr *)h->h_addr)));

    return 0;

}

编译 gcc gethostbyname.c -o gethostbyname。

执行./gethostbyname www.sina.com,执行结果如下:

Host name  : libra.sina.com.cn

IP Address : 202.108.33.83

摘录自《深入浅出Linux工具与编程》
0 0
原创粉丝点击