Linux Socket Programming by Example-第二章 IP 地址域 读书笔记

本文详细解析了Linux进程间通信中使用的本地域(AF_UNIX)和IP地址域(AF_INET),包括它们的数据结构、使用方法及与其他地址域的区别。重点介绍了如何在不同场景下选择合适的地址域进行通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

所谓的IP地址域名,通俗的理解就是对Socket端的一个标签。

比如,我们每个人有一个独一无二的身份证,身份证则属于国内公安管理域;我们出国则须要护照,这个属于世界范围内的身份域。

而在公司则有一个工号,这个属于公司身份域。

显然,不同的域有不同的规则,存储的信息也不一样。


同样,Socket用于不同的领域,也必然有不同的地址。

由于,早期BSD Socket还没有void *来封装内部不同的地址结构,通用IP地址的结构如下:

struct sockaddr

{
 unsigned short sa_family; /* address family */ |
 char sa_data[14]; /* up to 14 bytes of direct address */

};

早期,16位机器居多,sa_family为2个字节。

下面讲解Linux进程间通信常用的本地域(AF_LOCAL),也称(AF_UNIX)

我们都知道,在Linux中,最常见的标签就是文件路径。所以,本地域也是用独一无二的路径来表示。

#include <sys/un.h>

struct sockaddr_un {

sun_family sun_family;

char sun_path[108]; //注意,最后一位不需要存储'\0'

};

使用方法:

// 选择一个存在的路径,通常使用/tmp。

const char pth_unix[]       /* pathname */ 
            = "/tmp/my_sock"; 
        // 创建一个无名的Socket,这个时候该socket显然无法跨进程通信。
        sck_unix = socket(AF_UNIX,SOCK_STREAM,0); 
        if ( sck_unix == -1 ) 
            return -1; //错误处理代码。 
 
unlink(pth_unix); //保险起见,先删除文件。

        //初始化并设置adr_unix。
  memset(&adr_unix,0, sizeof adr_unix); 
dr_unix.sun_family = AF_UNIX; 
strncpy(adr_unix.sun_path,pth_unix, 
           sizeof adr_unix.sun_path-1) 
            [sizeof adr_unix.sun_path-1] = 0; 

        //将路径与前面创建的无名Socek进行绑定。
        len_unix = SUN_LEN(&adr_unix); 
        z = bind(sck_unix, 
            (struct sockaddr *)&adr_unix, 
            len_unix); 


本地域,由于使用的是Linux系统的文件路径,很显然只能跨进程通信。为了实现PC间的网络通信,

我们必须使用一种新的域,即IP 地址域(AF_INET)。我们将Socket同每台PC的IP地址进行绑定

IP地址有2个协议,IPv4和IPv6. IPv4是32位,而IPv6是128位。这里只重点介绍IPv4域。

#include <netinet/in.h>

struct sockaddr_in { 
    sa_family_t    sin_family;  /* Address Family */ 
    uint16_t       sin_port;     /* Port number */ 
    struct in_addr sin_addr;     /* Internet address */ 
    unsigned char  sin_zero[8];  /* Pad bytes */ 
}; 
 
 
struct in_addr { 
    uint32_ t       s_ addr;      /* Internet address */
};


注意,由于历史的原因,不同芯片存储数据的字节顺序是不一样的。以整数0x12345678为例。

Littel-Endian  0x78 0x56 0x34 0x12

Big-Endian  0x12 0x34 0x56 0x78 

★网络序是Big-Endian

 在实际项目中用以下宏判断:

#define IS_BigEndian(value)    {  int x = 0x12345678; unsigned char test = *((unsigned char*)&x); value = (test == 0x12) ? 1 : 0;}


这样便有一个网络顺序与PC本地顺序间的不一致问题。为了解决这一问题,

系统提供了相关的转换函数。h -> host 本地  n-> network 网络. s: 16bit l :32bit

unsigned long htonl(unsigned long hostlong);    
unsigned short htons(unsigned short hostshort);
unsigned long ntohl(unsigned long netlong); 
unsigned short ntohs(unsigned short netshort);


使用方法和上面的本地域基本一样,只是数据结构的设置有差别,数据的初始化方法如下:

struct sockaddr_in adr_inet;/* AF_INET */ 
 int le n_inet;                /* length  */
 const unsigned char IPno[] = { 
           127, 0, 0, 23     /* Local loopback */   // 127.0.0.23
        }; 
 memset(&adr_inet,0,sizeof adr_inet); 

adr_inet.sin_family = AF_INET; 

adr_inet.sin_port = htons(9000);   // port = 9000

memcpy(&adr_inet.sin_addr.s_addr,IPno,4);


接下来,书中还提到了其他几种地址域。

X.25 Address:

#include <linux/x25.h>

struct sockaddr_x25 { 
    sa_family_t  sx25_family; /* Must be AF_X25 */
    x25_address  sx25_addr;   /* X.121 Address */ 
}; 
 
typedef struct { 
    char          x25_addr[16]; 
} x25_address;


使用:

struct sockaddr_x25 adr_x25;/* AF_X25 */ 

const char x25_host[]   /* X.121 addr */ 
= "79400900"; 

adr_x25.sx25_family = AF_X25; 
strcpy(adr_x25.sx25_addr.x25_addr,x25_host);

小技巧:

 cat  /proc/net/x25 查看系统当前X.25 Socket连接信息。


AF_INET6— IPv6 下一代IP地址

struct sockaddr_in6 { 
    sa_family_t      sin6_family; 
    uint16_t         sin6_port;         /* port # */
    uint32_t         sin6_flowinfo; /* flow info */ 
    struct in6_addr sin6_addr;  /* IPv6 address */ 
}; 
 
 
struct in6_addr { 
    union { 
        uint8_t      u6_addr8[16]; 
        uint16_t     u6_addr16[8]; 
        uint32_t     u6_addr32[4];

   } in6_u; 

};
• AF_AX25— Amateur Radio X.25 protocol
• AF_APPLETALK— Linux AppleTalk protocol implementation

具体数据结构请百度或参考书本。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值