struct sockaddr与struct sockaddr_in ,struct sockaddr_un的区别和联系_struct sockaddr与struct sockaddr_un-程序员宅基地

技术标签: Socket  

sockaddr

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

struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,二者长度一样,都是16个字节。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。一般情况下,需要把sockaddr_in结构强制转换成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地址

sockaddr_in和sockaddr是并列的结构,指向sockaddr_in的结构体的指针也可以指向
sockadd的结构体,并代替它。也就是说,你可以使用sockaddr_in建立你所需要的信息,
在最后用进行类型转换就可以了。bzero((char*)&mysock,sizeof(mysock));//初始化
mysock结构体名
mysock.sa_family=AF_INET;
mysock.sin_addr.s_addr=inet_addr("192.168.0.1");
……
等到要做转换的时候用:
(struct sockaddr*)mysock

 

通常的用法是:

int sockfd;
struct sockaddr_in my_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0); 

my_addr.sin_family = AF_INET; /* 主机字节序 */
my_addr.sin_port = htons(MYPORT); /* short, 网络字节序 */

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

bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */
//memset(&my_addr.sin_zero, 0, 8);

bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));

#define UNIX_PATH_MAX 108

  struct sockaddr_un {

  sa_family_t sun_family; /*PF_UNIX或AF_UNIX */

  char sun_path[UNIX_PATH_MAX]; /* 路径名 */

  };

几点注意:
1:BSD网络软件中包含了两个函数,用来在二进制地址格式和点分十进制字符串格式之间相互转换,但
是这两个函数仅仅支持IPv4。
       in_addr_t inet_addr(const char *cp);
       char *inet_ntoa(struct in_addr in);
功能相似的两个函数同时支持IPv4和IPv6
       const char *inet_ntop(int domain, const void *addr, char *str, socklen_t size);
       int inet_pton(int domain, const char *str, void *addr);
2:Sockfd是调用socket函数返回的socket描述符,my_addr是一个指向包含有本机IP地址及端口号等信
息的sockaddr类型的指针;addrlen常被设置为sizeof(struct sockaddr)。
  struct sockaddr结构类型是用来保存socket信息的: 
  struct sockaddr { 
   unsigned short sa_family; /* 地址族, AF_xxx */ 
char sa_data[14]; /* 14 字节的协议地址 */ 
}; 
  sa_family一般为AF_INET,代表Internet(TCP/IP)地址族;sa_data则包含该socket的IP地址和端口号。 
  另外还有一种结构类型: 
  struct sockaddr_in { 
   short int sin_family; /* 地址族 */ 
   unsigned short int sin_port; /* 端口号 */ 
   struct in_addr sin_addr; /* IP地址 */ 
   unsigned char sin_zero[8]; /* 填充0 以保持与struct sockaddr同样大小 */ 
  }; 
这个结构更方便使用。sin_zero用来将sockaddr_in结构填充到与struct sockaddr同样的长度,
可以用bzero()或memset()函数将其置为零。指向sockaddr_in 的指针和指向sockaddr的指针可以相
互转换,这意味着如果一个函数所需参数类型是sockaddr时,你可以在函数调用的时候将一个指向 
sockaddr_in的指针转换为指向sockaddr的指针;或者相反。
3:你只要记住,填值的时候使用sockaddr_in结构,而作为函数的 
参数传入的时候转换成sockaddr结构就行了,毕竟都是16个字符 
长。


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; 
} S_un };


sockaddr_un
进程间通信的一种方式是使用UNIX套接字,人们在使用这种方式时往往用的不是网络套接字,而是一种称为本地套接字的方式。这样做可以避免为黑客留下后门。

struct sockaddr_un {

  sa_family_t sun_family; /*PF_UNIX或AF_UNIX */

  char sun_path[UNIX_PATH_MAX]; /* 路径名 */

  };
首先这个结构体是用来本地通信用的,并不是什么tcp/ip通信,虽然代码模式上很相似,准确的说是unix 
Domain 的通信,二者有本质上的区别,那个sun_path成员也就是担任这个domain(域)的角色了,比如存储
“/tmp/mydomain”这样的东西,再比如A和B之间通信,A应该有一个类似"/tmp/A"(名字可以自己随意起)的
域,B应该有一个类似"/tmp/B"的域,通信时分别向对方的域发送消息,从自己的域接受消息。A和B通信时都
是各自初始化对方的域,而创建本身的套接字的时候是初始化自身的 


unix domain的socket通信和网络socket不同的地方在于地址格式不同,用结构体sockaddr_un表示,网络编
程的socket地址是IP地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的
路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存在,则bind()错误返回。

创建
使用套接字函数socket创建,不过传递的参数与网络套接字不同。域参数应该是PF_LOCAL或者PF_UNIX,而不能用PF_INET之类。本地套接字的通讯类型应该是SOCK_STREAM或SOCK_DGRAM,协议为默认协议。例如:
 int sockfd;
 sockfd = socket(PF_LOCAL, SOCK_STREAM, 0);

绑定
创建了套接字后,还必须进行绑定才能使用。不同于网络套接字的绑定,本地套接字的绑定的是struct sockaddr_un结构。struct sockaddr_un结构有两个参数:sun_family、sun_path。sun_family只能是AF_LOCAL或AF_UNIX,而sun_path是本地文件的路径。通常将文件放在/tmp目录下。例如:

 struct sockaddr_un sun;
 sun.sun_family = AF_LOCAL;
 strcpy(sun.sun_path, filepath);
 bind(sockfd, (struct sockaddr*)&sun, sizeof(sun));

监听
本地套接字的监听、接受连接操作与网络套接字类似。

连接
连接到一个正在监听的套接字之前,同样需要填充struct sockaddr_un结构,然后调用connect函数。

连接建立成功后,我们就可以像使用网络套接字一样进行发送和接受操作了。甚至还可以将连接设置为非阻塞模式,这里就不赘述了。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_30736309/article/details/90750898

智能推荐

VUE 使用 IView 实现Table Tree进行异步数据加载_iview table tree-程序员宅基地

文章浏览阅读2.3k次。VUE 使用 IView 实现Table Tree进行异步数据加载页面布局 <Table ref="thisTab" row-key="ID" :load-data="handleLoadData" :columns="columnsList" :data="familyList" :highlight-row="true" :disabled-hover=._iview table tree

matlab飞机飞行模型,使用 MATLAB/Simulink 设计无人机飞行控制系统(二、动力学模型建立)...-程序员宅基地

文章浏览阅读8.7k次,点赞5次,收藏110次。前面一篇文章已经讲解了如何获取无人机的气动参数,本篇文章讲解如何建立无人机动力学模型。建立无人机动力学模型前面我们用 MATLAB 绘制了飞机的几何外形,并调用 DATCOM计算了无人机的气动参数。我们现在看一看 DATCOM 输出的 .out 文件是什么样的。我们又该怎么利用它呢?通过 DATCOM 计算得到的气动参数文件这是一个非常复杂的文件,里面记录了我们之前定义的各种飞行包线内的工作点上,..._大飞机数学模型matlab

cmake编译opencv: Win10+cmake3.14.4+cuda10.0+cudnn7.6+opencv-4.0.0+contrib+vs2015_opencv cudnn cmake-程序员宅基地

文章浏览阅读7.9k次,点赞15次,收藏31次。cmake编译opencv:Win10+opencv-3.4.0+contrib+cuda10.1+cudnn10.1+vs2013+cmake3.14.4安装所需软件/库欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定..._opencv cudnn cmake

dlib 人脸特征点检测_ndlb特征检测-程序员宅基地

文章浏览阅读4.7k次,点赞2次,收藏31次。人脸特征点检测(Facial landmark detection),即人脸特征点定位、人脸对齐,是在人脸检测的基础上进行的,对人类脸上的特征点(嘴角、眼角等)进行定位。人脸特征点检测有诸多用途:改善人脸识别:通过人脸特征点检测将人脸对齐到平均脸,对齐后的人脸图像识别算法更加有效。 人脸平均:利用人脸特征点检测的结果,将多个人脸进行融合,形成新的平均人脸。 人脸交换:利用人脸特征点检测..._ndlb特征检测

mysql计算俩个日期之间的天数_mysql计算两个日期之间的天数-程序员宅基地

文章浏览阅读9.3k次,点赞3次,收藏8次。1.利用TO_DAYS(date)函数例如:SELECT TO_DAYS(NOW()) - TO_DAYS('20200721')2.利用DATEDIFF(expr1,expr2)函数例如:select DATEDIFF(NOW(),'20200721')3.利用TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)函数这个函数可计算俩日期时间之间相差的天数、秒数、分钟数、周数、小时数,取决于unit参数的取值。该参数具体释义如下:_mysql计算两个日期之间的天数

【Unity】技巧集合_unityeditorinternal.animatorcontroller-程序员宅基地

文章浏览阅读527次。转发,请保持地址:http://blog.csdn.net/stalendp/article/details/17114135这篇文章将收集unity的相关技巧,会不断地更新内容。1)保存运行中的状态unity在运行状态时是不能够保存的。但在运行时编辑的时候,有时会发现比较好的效果想保存。这时可以在 “Hierarchy”中复制相关对象树,暂停游戏后替换原来的,就可以了_unityeditorinternal.animatorcontroller

随便推点

echarts的legend——图例样式的配置_echarts legend-程序员宅基地

文章浏览阅读3.1w次,点赞25次,收藏60次。echarts官网配置项手册里有非常详细的内容,我们挑几种常用的看看,加深对legend属性的理解。echarts图表中的图例,有形状,颜色,位置等等各种样式的不同配置。以上几张图表中,红色圆圈部分即图例。_echarts legend

数仓维度建模之维度表设计(设计实操二)_维度建模设计和实施过程-程序员宅基地

文章浏览阅读2.9k次,点赞2次,收藏22次。概述维度建模是一种将数据结构化的逻辑设计方法,它将客观世界划分为度量和上下文。度量是常常是以数值形式出现,事实周围有上下文包围着,这种上下文被直观地分成独立的逻辑块,称之为维度。它与实体-关系建模有很大的区别,实体-关系建模是面向应用,遵循第三范式,以消除数据冗余为目标的设计技术。维度建模是面向分析,为了提高查询性能可以增加数据冗余,反规范化的设计技术。维度建模优点事实表事实表存储了从..._维度建模设计和实施过程

修改表字段长度sql-程序员宅基地

文章浏览阅读1.2w次,点赞2次,收藏6次。ALTER TABLE 表名 MODIFY COLUMN 字段名 数据类型(修改后的长度)alter table EXAM_TEST modify STU_NAME VARCHAR2(100);alter table EXAM_TEST modify STU_NAME VARCHAR2(100);_修改表字段长度

Unity零基础到入门 ️| 游戏引擎 Unity 从0到1的 系统学习 路线【全面总结-建议收藏】!_unity学习路线-程序员宅基地

文章浏览阅读10w+次,点赞1.4k次,收藏7.3k次。Unity基础知识学习,Unity学习路线总结。本篇文章对Unity的学习路线做了一个全面系统的总结,对Unity有兴趣的小伙伴福利到了!敬请品尝~_unity学习路线

计算机缺少codex64.dll,win10x64缺少dll依赖库致使程序无法运行-程序员宅基地

文章浏览阅读4.1k次。尝试过安装VisualC++RedistributableforVisualStudio2015但还是未能解决问题缺失文件如下:API-MS-WIN-CORE-APIQUERY-L1-1-0.DLLAPI-MS-WIN-CORE-APPCOMPAT-L1-1-0.DLLAPI-MS-WIN-CORE-APPCOMPAT-L1-1-1.DLLAPI-MS-WIN-CORE-APPINIT..._codex64.dll

Android学习笔记_76_Android ProgressBar 进度条-程序员宅基地

文章浏览阅读72次。android 进度条的样式例1:(默认样式(中等圆形))Xml代码<ProgressBar android:id="@+id/progressBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" />例2:(超大圆形)Xml..._android:max=100”和 android:progress=”50”分别设置的是进度条的什么值?