struct sockaddr和struct sockaddr_in结构

sockaddr结构体
sockaddr的缺陷:sa_data把目标地址和端口信息混在一起了
struct sockaddr {
        ushort  sa_family;
        char    sa_data[14];
};
sa_family是通信类型,最常用的值是 "AF_INET"
sa_data14字节,包含套接字中的目标地址和端口信息
sockaddr_in 结构体

sockaddr_in结构体解决了sockaddr的缺陷,把port和addr 分开储存在两个变量中
struct sockaddr_in {
        short   sin_family;
        u_short sin_port;
        <span style="color:#3333ff;">struct  in_addr sin_addr;</span>
        char    sin_zero[8];
};

/* Internet address. */
struct in_addr {
    unsigned long   s_addr;     /* address in network byte order */
};
sin_zero 初始值应该使用函数 bzero() 来全部置零。
 
  一般采用下面语句
struct sockaddr_in cliaddr;
bzero(&cliaddr,sizeof(cliaddr));
  

 
  sockaddr_in结构体变量的基本配置
struct sockaddr_in ina;

bzero(&ina,sizeof(ina));

ina.sin_family=AF_INET;

ina.sin_port=htons(23);
ina.sin_addr.s_addr =inet_addr("132.241.5.10");  

sockaddr 和 sockaddr_in的相互关系

一般先把sockaddr_in变量赋值后,强制类型转换后传入用sockaddr做参数的函数

 
 
  •    sockaddr_in用于socket定义和赋值
  •    sockaddr用于函数参数
最典型的源、目的节点socket定义

对于源、目的地址和源、目的地址端口,需要建立两个socket变量
cliaddr绑定源地址和源端口
servaddr用于connect和sendto的设定目的地址和目的端口
struct sockaddr_in servaddr,cliaddr;

create_socket(char *server_addr_string,unsigned int server_port)
{
源socket赋值
       bzero(&cliaddr,sizeof(cliaddr));
       cliaddr.sin_family = AF_INET;
       通常TCP/UDP 协议源地址和端口都是随机的
       cliaddr.sin_addr.s_addr = htons(INADDR_ANY);
       cliaddr.sin_port = htons(0);

目的socket赋值
       bzero(&servaddr,sizeof(servaddr));
       servaddr.sin_family = AF_INET;
       inet_aton(server_addr_string,&servaddr.sin_addr);
       servaddr.sin_port = htons(server_port);
}
网络字节顺序 (Network ByteOrder)     NBO
结构体的sin_port和sin_addr都必须是NBO

   本机字节顺序 (Host ByteOrder)   HBO
一般可视化的数字都是HBO

    NBO,HBO二者转换
inet_addr()   将字符串点数格式地址转化成无符号长整型(unsigned long s_addr s_addr;)
inet_aton()   将字符串点数格式地址转化成NBO
inet_ntoa ()   将NBO地址转化成字符串点数格式
htons()   "Host to Network Short"
htonl()    "Hostto Network Long"
ntohs()   "Network to Host Short"
ntohl()   "Network to Host Long"
常用的是htons(),inet_addr()正好对应结构体的端口类型和地址类型

注意,inet_addr()返回的地址已经是网络字节格式,所以你无需再调用 函数htonl()。

三种给socket赋值地址的方法

 
 
inet_aton(server_addr_string,&myaddr.sin_addr);
myaddr.sin_addr.s_addr = inet_addr("132.241.5.10");
INADDR_ANY转不转NBO随便 myaddr.sin_addr.s_addr =htons(INADDR_ANY);   myaddr.sin_addr.s_addr = INADDR_ANY;
两种给socket赋值端口的方法

 
 
#define MYPORT 3490  myaddr.sin_port = htons(MYPORT);
0(随机端口)转不转NBO随便 myaddr.sin_port = htons(0); myaddr.sin_port = 0;  
htons/l和ntohs/l等数字转换都不能用于地址转换,因为地址都是点数格式,所以地址只能采用数字/字符串转换如inet_aton,inet_ntoa;

唯一可以用于地址转换的htons是针对INADDR_ANY
 cliaddr.sin_addr.s_addr = htons(INADDR_ANY)
inet_addr()与inet_aton()的区别

 
 
  •    inet_addr()   是返回值型
struct sockaddr_in ina; ina.sin_addr.s_addr =inet_addr("132.241.5.10"); 
  •    inet_aton()    是参数指针型
struct sockaddr_in ina; inet_aton("132.241.5.10",&ina.sin_addr);
inet_ntoa 将NBO地址转化成字符串点数格式
参数:结构体变量.sinaddr

返回值:字符串指针

 
 
a1 = inet_ntoa(ina.sin_addr); printf("address 1: %s\n",a1); 
address 1: 132.241.5.10 
  inet_addr()的缺陷:必须对-1做检测处理

因为inet_addr()的结果是整型,而发生错误时返回-1。
而 ina.sin_addr.s_addr是unsigned long型
-1在long short显示成111111111,和IP地址255.255.255.255相符合!会被误认为广播地址!
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值