struct sockaddr和struct sockaddr_in这两个结构体用来处理网络通信的地址。

一、sockaddr

sockaddr在头文件#include <sys/socket.h>中定义,sockaddr的缺陷是:sa_data把目标地址和端口信息混在一起了,如下:

  1.  
    struct sockaddr {
  2.  
    sa_family_t sin_family;//地址族
  3.  
       char sa_data[14]; //14字节,包含套接字中的目标地址和端口信息
  4.  
       };

二、sockaddr_in

sockaddr_in在头文件#include<netinet/in.h>或#include <arpa/inet.h>中定义,该结构体解决了sockaddr的缺陷,把port和addr 分开储存在两个变量中,如下: 

sin_port和sin_addr都必须是网络字节序(NBO),一般可视化的数字都是主机字节序(HBO)。

三、总结

二者长度一样,都是16个字节,即占用的内存大小是一致的,因此可以互相转化。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。

sockaddr常用于bind、connect、recvfrom、sendto等函数的参数,指明地址信息,是一种通用的套接字地址。 
sockaddr_in 是internet环境下套接字的地址形式。所以在网络编程中我们会对sockaddr_in结构体进行操作,使用sockaddr_in来建立所需的信息,最后使用类型转化就可以了。一般先把sockaddr_in变量赋值后,强制类型转换后传入用sockaddr做参数的函数:sockaddr_in用于socket定义和赋值;sockaddr用于函数参数。

例子如下:

  1.  
    #include <stdio.h>
  2.  
    #include <stdlib.h>
  3.  
    #include <sys/socket.h>
  4.  
    #include <netinet/in.h>
  5.  
     
  6.  
    int main(int argc,char **argv)
  7.  
    {
  8.  
    int sockfd;
  9.  
    struct sockaddr_in mysock;
  10.  
     
  11.  
    sockfd = socket(AF_INET,SOCK_STREAM,0); //获得fd
  12.  
     
  13.  
    bzero(&mysock,sizeof(mysock)); //初始化结构体
  14.  
    mysock.sin_family = AF_INET; //设置地址家族
  15.  
    mysock.sin_port = htons(800); //设置端口
  16.  
    mysock.sin_addr.s_addr = inet_addr("192.168.1.0"); //设置地址
  17.  
    bind(sockfd,(struct sockaddr *)&mysock,sizeof(struct sockaddr); /* bind的时候进行转化 */
  18.  
    ... ...
  19.  
    return 0;
  20.  
    }

题外话,两个函数 htons() 和 inet_addr()。

htons()作用是将端口号由主机字节序转换为网络字节序的整数值。(host to net)

inet_addr()作用是将一个IP字符串转化为一个网络字节序的整数值,用于sockaddr_in.sin_addr.s_addr。

inet_ntoa()作用是将一个sin_addr结构体输出成IP字符串(network to ascii)。比如:

printf("%s",inet_ntoa(mysock.sin_addr));
  • 1

htonl()作用和htons()一样,不过它针对的是32位的(long),而htons()针对的是两个字节,16位的(short)。

与htonl()和htons()作用相反的两个函数是:ntohl()和ntohs()。 

addrinfo结构体原型

typedef struct addrinfo {
    int ai_flags;        //AI_PASSIVE,AI_CANONNAME,AI_NUMERICHOST
    int ai_family;        //AF_INET,AF_INET6
    int ai_socktype;    //SOCK_STREAM,SOCK_DGRAM
    int ai_protocol;    //IPPROTO_IP, IPPROTO_IPV4, IPPROTO_IPV6 etc.
    size_t ai_addrlen;            //must be zero or a null pointer
    char* ai_canonname;            //must be zero or a null pointer
    struct sockaddr* ai_addr;    //must be zero or a null pointer
    struct addrinfo* ai_next;    //must be zero or a null pointer
}

其中ai_flags、ai_family、ai_socktype说明如下:
参数            取值            值            说明
ai_family        AF_INET            2            IPv4
                AF_INET6        23            IPv6
                AF_UNSPEC        0            协议无关
ai_protocol        IPPROTO_IP        0            IP协议
                IPPROTO_IPV4    4            IPv4
                IPPROTO_IPV6    41            IPv6
                IPPROTO_UDP        17            UDP
                IPPROTO_TCP        6            TCP
ai_socktype        SOCK_STREAM        1            流
                SOCK_DGRAM        2            数据报
ai_flags        AI_PASSIVE        1            被动的,用于bind,通常用于server socket
                AI_CANONNAME    2
                AI_NUMERICHOST    4            地址为数字串

对于ai_flags值的说明:
AI_NUMERICHOST | AI_CANONNAME | AI_PASSIVE
如上表所示,ai_flags的值范围为0~7,取决于程序如何设置3个标志位,比如设置ai_flags为 “AI_PASSIVE|AI_CANONNAME”,ai_flags值就为3。三个参数的含义分别为:
(1)AI_PASSIVE当此标志置位时,表示调用者将在bind()函数调用中使用返回的地址结构。当此标志不置位时,表示将在connect()函数调用中使用。当节点名位NULL,且此标志置位,则返回的地址将是通配地址。如果节点名NULL,且此标志不置位,则返回的地址将是回环地址。
(2)AI_CANNONAME当此标志置位时,在函数所返回的第一个addrinfo结构中的ai_cannoname成员中,应该包含一个以空字符结尾的字符串,字符串的内容是节点名的正规名。
(3)AI_NUMERICHOST当此标志置位时,此标志表示调用中的节点名必须是一个数字地址字符串。

结构体addrinfo, sockaddr, sockaddr_in的区别的更多相关文章

  1. C结构体、C++结构体、C++类的区别

    先来说说C和C++中结构体的不同 a) C语言中的结构体不能为空,否则会报错 1>d:\myproject\visual studio 2013\projects\myc++\main.c(71 ...

  2. 关于c#的结构体struct与class的区别

    C# 结构体 struct C#中结构类型和类类型在语法上非常相似,他们都是一种数据结构,都可以包括数据成员和方法成员. 结构和类的区别: 1.结构是值类型,它在栈中分配空间:而类是引用类型,它在堆中 ...

  3. MATLAB 单元数组 cell 和结构体 struct 的用法以及区别

    1. 前言 Matlab单元数组cell和结构体struct都可以将不同类型的相关数据集成到一个单一的变量中,使得大量的相关数据的处理变得非常简单而且方便.但是,需要注意的是,单元数组和结构体只是承载 ...

  4. C语言结构体指针与结构体变量作形参的区别

    区别 结构体变量 结构体变量作为形参,传递的是结构体变量本身,是一种值传递 形参结构体变量成员值的改变不影响对应的实参构体变量成员值的改变 结构体指针 结构体指针作为函数参数,传递的是指向结构体变量的 ...

  5. C++结构体定义和C的区别

    对于C来说,struct定义的结构体不是一种数据类型,所以每次声明的时候需要加上struct让编译器知道这是结构体,为了不每次都加上struct关键字,可以在定义结构体的时候加上typedef关键字: ...

  6. 结构体sockadrr、sockaddr_in、in_addr的定义

    /* Internet address.  */typedef uint32_t in_addr_t;struct in_addr  {    in_addr_t s_addr;  };  typed ...

  7. socket编程——sockaddr_in结构体操作

    sockaddr结构体 sockaddr的缺陷: struct sockaddr 是一个通用地址结构,这是为了统一地址结构的表示方法,统一接口函数,使不同的地址结构可以被bind() , connec ...

  8. TinyHttpd中sockaddr与struct sockaddr_in的区别

    上午学习TinyHttpd的源码,sockaddr 结构体以前没接触过, 在网络编程中经常用到struct sockaddr和struct sockaddr_in,这里简单介绍. 在linux环境下, ...

  9. IPv4地址结构体sockaddr_in详解

    sockaddr_in结构体定义 struct sockaddr_in { sa_family_t sin_family; //地址族(Address Family) uint16_t sin_por ...

随机推荐

  1. 《JavaScript高级程序设计》笔记:函数表达式(七)

    递归 function factorial(num){ if(num<=1){ return 1; }else { return num * arguments.callee(num-1); } ...

  2. Linux安装配置Mariadb

    一.安装数据库Mariadb 参考:http://blog.51cto.com/12173069/2047746 从最新版本的linux系统开始,默认的是 Mariadb而不是mysql! 使用系统自 ...

  3. CTF杂项之BubbleBabble加密算法

    这题很坑,刚开始我拿到就分析不出来了(/无奈),关键是不知道是什么加密算法,后来看题目描述的bubble,猜测是bubble 这种算法(听都没听说过...) 上图 这串编码 xinik-samak-l ...

  4. RabbitMQ消息模型概览(简明教程)

    小菜最近用到RabbitMQ,由于之前了解过其他消息中间件,算是有些基础,所以随手从网上搜了几篇文章,准备大概了解下RabbitMQ的消息模型,没想到网上文章千篇一律,写一大堆内容,就是说不明白到底怎 ...

  5. 求出100以内的素数(java实现)

    j package test1; //2018/11/30 //求100以内的所有素数 public class Main10 { public static void main(String[] a ...

  6. 【java学习】Intelli Idea集成开发工具的使用

    == mac版直接下载地址: https://download.jetbrains.com/idea/ideaIU-2018.1.6.dmg   ==mac配置java环境变量: https://ji ...

  7. 影响Linux发展的四位天才黑客

    影响Linux发展的四位天才黑客 相信大家对 Linux 再熟悉不过了.我们都知道 Linux继承自 Unix,但其实他们上一代还有一个 Multics.从最早的 Multics 发展到最早版本的 L ...

  8. php之微信公众号发送模板消息参观模仿

    上篇文章中鞋到了公众号发送末班消息,他是最后调用两个方法,本文章简化一下 将下面的php方法放到一个可以引入的公共类中即可 构建模板消息: 我把需要用到的模板消息 都写成一个个方法,放在公共类文件中了 ...

  9. python官网几个下载文件的区别

    进入python官方,下载python编译器,提供了如下几个版本进行选择,这些版本分别是什么意思呢? Python 3.7.1 - 2018-10-20 Download Windows x86 we ...

  10. Java导出压缩包工具类

    /** * @Title: exportZip * @Description:TODO(导出建压缩文件) * @param delAdviceinfo 为项目实体类 * @date 2018年4月4日 ...