socket结构和IP地址形式间转换的总结

来源:互联网 发布:python游戏开发入门 编辑:程序博客网 时间:2024/05/18 10:22


 sockaddr 

sockaddr_in 

addrinfo

比较

 

 

struct sockaddr { 

unsigned  short  sa_family;     /* address family, AF_xxx */ 

char  sa_data[14];                 /* 14 bytes of protocol address */ 

}; 

sa_family

是地址家族,一般都是“

AF_xxx

”的形式。好像通常大多用的是都是

AF_INET

 

sa_data

14

字节协议地址。

 

此数据结构用做

bind

connect

recvfrom

sendto

等函数的参数,指明地址信

息。

 

但一般编程中并不直接针对此数据结构操作,而是使用另一个与

sockaddr

等价的

数据结构

 

sockaddr_in

(在

netinet/in.h

中定义)

 

struct  sockaddr_in { 

short  int  sin_family;                      /* Address family */ 

unsigned  short  int  sin_port;       /* Port number */ 

struct  in_addr  sin_addr;              /* Internet address */ 

unsigned  char  sin_zero[8];         /* Same size as struct sockaddr */ 

}; 

struct  in_addr { 

unsigned  long  s_addr; 

}; 

typedef struct in_addr { 

union { 

            struct{ 

                        unsigned char s_b1, 

                        s_b2, 

                        s_b3, 

                        s_b4; 

                        } S_un_b; 

           struct { 

                        unsigned short s_w1, 

                        s_w2; 

                        } S_un_w; 

            unsigned long S_addr; 

          } S_un; 

} IN_ADDR; 

sin_family

指代协议族,在

socket

编程中只能是

AF_INET 

sin_port

存储端口号(使用

网络字节顺序

 

sin_addr

存储

IP

地址,使用

in_addr

这个数据结构

 

sin_zero

是为了让

sockaddr

sockaddr_in

两个数据结构保持大小相同而保留的

空字节

 

s_addr

按照

网络字节顺序

存储

IP

地址。

 

 

addrinfo

结构是

getaddrinfo

函数

用来保存主机地址信息的结构体。在头文件

Ws2tcpip.h

中定义。

 

typedef struct addrinfo { 

  int ai_flags; 

  int ai_family; 

  int ai_socktype; 

  int ai_protocol; 

  size_t ai_addrlen; 

  char* ai_canonname; 

  struct sockaddr* ai_addr; 

  struct addrinfo* ai_next; 

} ADDRINFOA,  *PADDRINFOA; 

ai_flags

:表示

getaddrinfo

要使用的选项,可赋的值在

Winsock2.h

中有定义,

且可以是几个值的组合。

 

ai_family

:地址族。一般为

AF_INET

 

ai_socktype

:套接字类型。

SOCK_STREAM

SOCK_DGRAM

SOCK_RAW

SOCK_RDM 

SOCK_SEQPACKET

 

ai_protocol

:协议类型。可取的值取决于

ai_address

ai_socktype

的值。

IPPROTO_TCP

IPPROTO_UDP

IPPROTO_RM

 

如果

ai_family

置为

AF_IRDA

,则

ai_protocol

必须为

0

 

ai_addrlen

ai_addr

指向的缓冲区的字节数。

 

ai_canonname

:主机的规范化名称(

canonical name

 

ai_addr

:指向

sockaddr

结构的指针。

 

 

IP

地址的网络字节顺序和机器字节顺序

     210.25.132.181

属于

IP

地址的

ASCII

表示法,也就是字符串形式。英语叫

IPv4 numbers-and-dots notation

 

    

如果把

210.25.132.181

转换为整数形式,是

3524887733

,这个就是整数形式

IP

地址。英语叫做

binary data

(其实

binary

是二进制的意思)

 

     Internet

地址用

.

间隔的地址可有下列几种表达方式:

 a.b.c.d

a.b.c

a.b

a  

 

当四个部分都有定值时,每个都解释成一个字节数据,从左到右组成

Internet

四字节地址。

Internet

地址以网络字节顺序返回

(

字节从左到右排列。

请注意,当一个

Internet

地址在

Intel

机器上表示成一个

32

位整型数时,则上述

的字节为“

d.c.b.a

。这是因为

Intel

处理器的字节是从右向左排列的。

 

上述中

的“

a.b.c.d

”就为网络字节顺序,而“

d.c.b.a

”则为机器字节顺序。

 

 

ntohs, ntohl, htons,htonl

的比较和详解

 

ip

地址是

32

位的端口号是

16

位的

 

 

ntohs =net to host short int 16

 

htons=host to net short int 16

 

ntohs =net to host long int 32

 

htonl=host to net long int  32

 

 u_short PASCAL FAR

 ntohs

( u_short netshort); 

      

netshort

:一个以网络字节顺序表达的

16

位数。本函数将一个

16

位数由网

络字节顺序转换为

16

位主机字节顺序。

 

 

 u_short PASCAL FAR 

htons

( u_short hostshort);  

       hostshort

:一个主机字节顺序表达的

16

位数。

 

本函数将一个

16

位数从主

机字节顺序转换成

16

位网络字节顺序。

 

 

 u_long PASCAL FAR

 htonl

( u_long hostlong);   

       

hostlong

:一个主机字节顺序表达的

32

位数。本

函数

将一个

32

位数从主机

字节顺序转换成

32

位网络字节顺序。

  

 

 u_long PASCAL FAR

 ntohl

( u_long netlong)

  

       

netlong

:一个以网络字节顺序表达的

32

位数。

 

本函数将一个

32

位数由

网络字节顺序转换为

32

位的主机字节顺序。

  

 

 inet_network()

inet_addr()

inet_aton()

inet_ntoa() 

 

int inet_aton(const char *string, struct in_addr *addr);  

in_addr_t inet_addr(const char *cp); 

in_addr_t inet_network(const char *cp); 

char FAR* PASCAL FAR inet_ntoa( struct in_addr in); 

 

函数

inet_addr()

:将

IP

地址从

 

点数格式转换成无符号长整型。使用方法如下:

 

ina.sin_addr.s_addr = inet_addr("132.241.5.10"); 

注意,

inet_addr()

返回的地址已经是网络字节格式,所以你无需再调用

 

函数

htonl()

 

 

函数

inet_network()

inet_network

inet_addr

函数都是用于将字符串形式转

换为整数形式用的,两者区别很小,

inet_addr

返回的整数形式是网络字节序,而

inet_network

返回的整数形式是主机字节序。

 

 

函数

int inet_aton(const char *string, struct in_addr *addr); 

       inet_aton()

是一个改进的方法来将一个字符串

IP

地址转换为一个

32

位的

网络序列

IP

地址。

输入参数

string

包含

ASCII

表示的

IP

地址。

  

 

输出参数

addr

是将要用新的

IP

地址更新的结构。

  

 

返回值:

  

如果这个函数成功,函数的

返回值非零。如果输入地址不正确则会返回零。使用这个函数并没有错误码存放

errno

中,所以他的值会被忽略。

 inet_aton

函数和上面这俩小子的区别就是

在于他认为

255.255.255.255

是有效的,他不会冤枉这个看似特殊的

IP

地址。

inet_aton

函数返回的是网络字节序的

IP

地址。如:

inet_aton("127.0.0.1",&adr_inet.sin_addr))  

 

函数

inet_ntoa()

:将网络地址转换成“

.

”点隔的字符串格式。本函数将一个用

in

参数所表示的

Internet

地址结构转换成以“

.

 

间隔的诸如“

a.b.c.d

”的字

符串形式。

请注意

inet_ntoa()

返回的字符串存放在

WINDOWS

套接口实现所分配的

内存中。

应用程序不应假设该内存是如何分配的。

在同一个线程的下一个

WINDOWS

套接口调用前,数据将保证是有效。返回值:

  

 

若无错误发生,

inet_ntoa()

返回一个字符指针。否则的话,返回

NULL

。其中的数据应在下一个

WINDOWS

套接

口调用前复制出来。函数

 inet_ntoa()("ntoa"

的含义是

"network to ascii")

就像这样:

 printf("%s",inet_ntoa(ina.sin_addr)); 

它将输出

IP

地址。

 

Inet_pton() 

inet_ntop() 

     Linux

下这

2

IP

地址转换函数,可以在将

IP

地址在“点分十进制”和“整

数”

之间转换

  

 

而且,

inet_pton

inet_ntop

2

个函数能够处理

ipv4

ipv6

算是比较新的函数了。

 

inet_pton

函数原型如下

[

将“点分十进制”

 

“整数”

]  

 

#include 

<sys/types.h> 

 

 

#include 

<sys/socket.h> 

 

 

#include 

<arpa/inet.h>  

 

int inet_pton(int af, const char *src, void *dst);  

 

这个函数转换字符

串到网络地址,第一个参数

af

是地址族,转换后存在

dst

 

 

inet_pton 

inet_addr

的扩展,

支持的多地址族有下列:

  

 

af 

AF_INET  

 

src

为指向字符型的地址,即

ASCII

的地址的首地址(

ddd.ddd.ddd.ddd

格式的)

函数将该地址

  

 

转换为

in_addr

的结构体,

并复制在

*dst

  

 

af 

=AF_INET6  

 

src

为指向

IPV6

的地址,

,函数将该地址

  

 

转换为

in6_addr

的结构体,并复制

*dst

  

 

如果函数出错将返回一个负值,并将

errno

设置为

EAFNOSUPPORT

如果参数

af

指定的地址族和

src

格式不对,函数将返回

0

  

    inet_ntop

函数原型如下

[

将“点分十进制”

 

“整数”

]  

 

#include 

<sys/types.h> 

 

 

#include 

<sys/socket.h> 

 

 

#include 

<arpa/inet.h>  

 

const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);  

 

这个函数转换网络二进制结构到

ASCII

类型的地址,参数的作用和上面相同,只

是多了一个参数

socklen_t cnt,

他是所指向缓存区

dst

的大小,避免溢出,如果

缓存区太小无法存储地址的值,则返回一个空指针,并将

errno

置为

ENOSPC

 

 

 

 

g

ethostbyname

gethostbyaddr

这两个函数仅仅支持

IPv4

getaddrinfo

数能够处理名字到地址以及服务到端口这两种转换,返回的是一个

sockaddr

结构的链表而不是一个地址清单。这些

sockaddr

结构随后可由套接口函数直

接使用。如此以来,

getaddrinfo

函数把协议相关性安全隐藏在这个库函数内

部。应用程序只要处理由

getaddrinfo

函数填写的套接口地址结构。该函数在

 

POSIX

规范中定义了。

 

 

#include<netdb.h> 

int 

getaddrinfo( 

const 

char 

*hostname, 

const 

char 

*service, 

const 

struct 

addrinfo *hints, struct addrinfo **result ); 

返回

0

  

成功

 

返回非

0

  

出错

 

 

hostname:

一个主机名或者地址串

(IPv4

的点分十进制串或者

IPv6

16

进制串

service

:一个服务名或者

10

进制端口号数串。

 

hints

:可以是一个空指针,也可以是一个指向某个

addrinfo

结构的指针,调

用者在这个结构中填入关于期望返回的信息类型的暗示。举例来说:如果指定

的服务既支持

TCP

也支持

UDP

那么调用者可以把

hints

结构中的

ai_socktype

成员设置成

SOCK_DGRAM

使得返回的仅仅是适用于数据报套接口的信息。

 

 

本函数通过

result

指针参数返回一个指向

addrinfo

结构链表的指针,而

addrinfo

结构定义在头文件

netdb.h

中:

 

struct addrinfo{ 

    int       ai_flags;   

    int       ai_family; 

    int       ai_socktype; 

0 0
原创粉丝点击