现在的位置: 首页 > 综合 > 正文

sockaddr_in和sockaddr二者区别

2013年12月03日 ⁄ 综合 ⁄ 共 6322字 ⁄ 字号 评论关闭


482人阅读
评论(0)
收藏
举报

  1. struct   sockaddr   {    
  2.     unsigned   short   sa_family;       
  3.     char   sa_data[14];       
  4. };    

sockaddr_in和sockaddr结构的关系

填值的时候使用sockaddr_in结构,而作为函数(如socket, listen, bind等)的参数传入的时候转换成sockaddr结构就行了,毕竟都是16个字符长。

 

上面是通用的socket地址,具体到Internet   socket,用下面的结构,二者可以进行类型转换  。

 

  1. struct   sockaddr_in   {    
  2.     short   int   sin_family;           //指代协议簇,在socket编程中只能使用AF_INET
      
  3.     unsigned   short   int   sin_port;  //端口号,使用网络字节顺序,因此要进行转换
      
  4.     struct   in_addr   sin_addr;     //struct in_addr 是存储ip地址,
      
  5.     unsigned   char   sin_zero[8];   //这儿为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。 
      
  6. };    

struct in_addr这个结构就是存储ip地址。

  1. typedef struct in_addr{  
  2.  union{     
  3.     struct {unsigned char s_b1,s_b2,s_b3,s_b4;} S_un_b;  
  4.     struct{ unsigned short s_w1,s_w2;} S_un_w;  
  5.     struct{unsigned long S_addr;} S_un;  
  6.     }   
  7. }IN_ADDR;   

下面举例说明一下用法

  1. /*sockadddr_in结构体用作bind、connect、recvfrom、sendto等函数的参数*/  
  2. int   sockfd;    
  3. sockfd   =   socket(AF_INET,   SOCK_STREAM,   0);    //socket函数创建一个socket,并指定通信方式。
      
  4.   
  5. struct   sockaddr_in   my_addr;    
  6. /*为此结构体赋值*/      
  7. my_addr.sin_family   =   AF_INET;       
  8. my_addr.sin_port   =   htons(MYPORT); //采用htons函数转换为网络字节序
      
  9. my_addr.sin_addr.s_addr   =   inet_addr("192.168.0.1");    
  10.   
  11. bzero(&(my_addr.sin_zero),   8);       
  12.   
  13. bind(sockfd,   (struct   sockaddr   *)&my_addr,   sizeof(struct   sockaddr));  

 

 

关于上面程序中部分难点的讲解。

(1)socket函数

函数原型: SOCKET socket(int af, int type, int protocal);

参数: af: 指代协议簇,在socket编程中只能使用AF_INET

type:为新的socket指定传输类型。在windows scokets只能使用以下两种类型

    SOCK_STREAM 即TCP

    SOCK_DGRAM即UDP

protocal:用于指定协议簇的特定协议,一般情况下赋值为0 是正确的。

函数功能:socket函数产生一个socket描述符,并与所分配的资源相联系,和绑定特定的传输服务。

返回值:如果没有错误发生,那么socket函数将返回一个指向新socket的描述符。否则,一个INVALID_SOCKET 值返回。

(2)

主机字节序:

不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。最常见的有两种 1.Little endian:低字节存高地址,高字节存低地址 2.Big endian:低字节存低地址,高字节存高地址

网络字节序:

网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。

为了进行转换bsd socket提供了转换的函数,有下面四个网络与主机字节转换函数:htons ntohs htonl ntohl (s 就是short l是long h是host n是network)

htons 把unsigned short类型从主机序转换到网络序,htonl 把unsigned long类型从主机序转换到网络序,ntohs 把unsigned short类型从网络序转换到主机序,ntohl 把unsigned long类型从网络序转换到主机序。

在使用little endian的系统中 这些函数会把字节序进行转换 在使用big endian类型的系统中这些函数会定义成空宏。

(3)

inet_addr()是将一个点分制的IP地址(如192.168.0.1)转换为上述结构中需要的32位IP地址(0xC0A80001)。

  1. struct   sockaddr   {    
  2.     unsigned   short   sa_family;       
  3.     char   sa_data[14];       
  4. };    

sockaddr_in和sockaddr结构的关系

填值的时候使用sockaddr_in结构,而作为函数(如socket, listen, bind等)的参数传入的时候转换成sockaddr结构就行了,毕竟都是16个字符长。

 

上面是通用的socket地址,具体到Internet   socket,用下面的结构,二者可以进行类型转换  。

 

  1. struct   sockaddr_in   {    
  2.     short   int   sin_family;           //指代协议簇,在socket编程中只能使用AF_INET
      
  3.     unsigned   short   int   sin_port;  //端口号,使用网络字节顺序,因此要进行转换
      
  4.     struct   in_addr   sin_addr;     //struct in_addr 是存储ip地址,
      
  5.     unsigned   char   sin_zero[8];   //这儿为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。 
      
  6. };    

struct in_addr这个结构就是存储ip地址。

  1. typedef struct in_addr{  
  2.  union{     
  3.     struct {unsigned char s_b1,s_b2,s_b3,s_b4;} S_un_b;  
  4.     struct{ unsigned short s_w1,s_w2;} S_un_w;  
  5.     struct{unsigned long S_addr;} S_un;  
  6.     }   
  7. }IN_ADDR;   

下面举例说明一下用法

  1. /*sockadddr_in结构体用作bind、connect、recvfrom、sendto等函数的参数*/  
  2. int   sockfd;    
  3. sockfd   =   socket(AF_INET,   SOCK_STREAM,   0);    //socket函数创建一个socket,并指定通信方式。
      
  4.   
  5. struct   sockaddr_in   my_addr;    
  6. /*为此结构体赋值*/      
  7. my_addr.sin_family   =   AF_INET;       
  8. my_addr.sin_port   =   htons(MYPORT); //采用htons函数转换为网络字节序
      
  9. my_addr.sin_addr.s_addr   =   inet_addr("192.168.0.1");    
  10.   
  11. bzero(&(my_addr.sin_zero),   8);       
  12.   
  13. bind(sockfd,   (struct   sockaddr   *)&my_addr,   sizeof(struct   sockaddr));  

 

 

关于上面程序中部分难点的讲解。

(1)socket函数

函数原型: SOCKET socket(int af, int type, int protocal);

参数: af: 指代协议簇,在socket编程中只能使用AF_INET

type:为新的socket指定传输类型。在windows scokets只能使用以下两种类型

    SOCK_STREAM 即TCP

    SOCK_DGRAM即UDP

protocal:用于指定协议簇的特定协议,一般情况下赋值为0 是正确的。

函数功能:socket函数产生一个socket描述符,并与所分配的资源相联系,和绑定特定的传输服务。

返回值:如果没有错误发生,那么socket函数将返回一个指向新socket的描述符。否则,一个INVALID_SOCKET 值返回。

(2)

主机字节序:

不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。最常见的有两种 1.Little endian:低字节存高地址,高字节存低地址 2.Big endian:低字节存低地址,高字节存高地址

网络字节序:

网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。

为了进行转换bsd socket提供了转换的函数,有下面四个网络与主机字节转换函数:htons ntohs htonl ntohl (s 就是short l是long h是host n是network)

htons 把unsigned short类型从主机序转换到网络序,htonl 把unsigned long类型从主机序转换到网络序,ntohs 把unsigned short类型从网络序转换到主机序,ntohl 把unsigned long类型从网络序转换到主机序。

在使用little endian的系统中 这些函数会把字节序进行转换 在使用big endian类型的系统中这些函数会定义成空宏。

(3)

inet_addr()是将一个点分制的IP地址(如192.168.0.1)转换为上述结构中需要的32位IP地址(0xC0A80001)。

抱歉!评论已关闭.