流沙团
sockaddr和sockaddr_in
2018-7-21 流沙团
sockaddr结构体



struct sockaddr { 

unsigned short sa_family; // 地址族, AF_xxx 

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


}; 







上面是通用的socket地址










sockaddr_in的结构体

struct sockaddr_in { 

short int sin_family; //地址族,AF_xxx 在socket编程中只能是AF_INET 

unsigned short int sin_port; // 端口号 (使用网络字节顺序) 

struct in_addr sin_addr; //存储IP地址 4字节

unsigned char sin_zero[8]; // 总共8个字节,实际上没有什么用,只是为了和struct sockaddr保持一样的长度 

}; 





两者可以进行相互转换。





struct in_addr就是32位IP地址。 





struct in_addr { 

  union {

    struct {

      u_char s_b1,s_b2,s_b3,s_b4; 

    } S_un_b;

    struct { 

      u_short s_w1,s_w2; 

    } S_un_w;

    u_long S_addr; //按照网络字节顺序存储IP地址 

  } S_un;

  #define s_addr S_un.S_addr

}; 

我们在为bind()函数准备ip、port值时,可以直接将值赋给结构体:sockaddr_in,请看下面的例子:





int serverfd = -1;

 

//本地地址、端口赋值

struct sockaddr_in sin;

//PROTOCL FAMILY 协议族,使用AF_INET、PF_INET都可以

sin.sin_family = PF_INET;

 

//htons()函数将一个16位的无符号短整型数据由主机分列体式格式转换成收集分列体式格式

sin.sin_port = htons(atoi("8183"));

 

//inet_addr()函数将网络地址转化为二进制数字

sin.sin_addr.s_addr = inet_addr("192.168.0.1");

serverfd = socket(sin.sin_family,SOCK_STREAM,IPPROTO_TCP);

if(serverfd < 0){

  printf("创建server的socket套接字失败");

  return -1;

}

 

bzero(&(sin.sin_zero), 8); // zero the rest of the struct 

ret = bind(serverfd,(const struct sockaddr*)&sin,sizeof(sin));

if(ret){

  printf("绑定本地地址、端口失败");

  return -1;


}







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






填值的时候使用sockaddr_in结构,而作为函数(如socket, listen, bind等)的参数传入的时候转换成sockaddr结构就行了,因为两个结构体都是16个字符长,可以相互转换。
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容