linux网络编程---IP地址

目录

一、Linux下IP地址的表示方式

1.1、通用套接字的地址类型定义如下:

1.2、以太网中的地址类型表示

1.3、结构sockaddr和结构sockaddr_in的关系

1.4、本地socket中使用的地址类型

二、IP地址的转换

  2.1 字符串IP与二进制IP地址的转换

2.2 IP转换函数之通用的版本


一、Linux下IP地址的表示方式

在socket编程中,地址结构通常都是以sockaddr_开头的,不同的协议族有不同的地址后缀定义方式

1.1、通用套接字的地址类型定义如下:

struct sockaddr
{
    sa_family_t sa_family;	/* Common data: address family and length.  */
    char sa_data[14];		/* Address data.  */
};

上述结构中,定义在头文件<ifaddrs.h>中,sa_family_t实际上是 unsigned short int类型,故该结构的共占用16个字节。

1.2、以太网中的地址类型表示

从上面可以看出,在以太网编程中,使用struct sockaddr结构并不是很方便,没法直观的标示IP地址和端口等相关的信息,为此在以太网编程中,使用struct sockaddr_in来描述网络地址信息,其结构如下:

struct sockaddr_in
  {
    sa_family_t sin_family;
    in_port_t sin_port;			/* Port number.  */
    struct in_addr sin_addr;		/* Internet address.  */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr)
			   - __SOCKADDR_COMMON_SIZE
			   - sizeof (in_port_t)
			   - sizeof (struct in_addr)];
  };

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

上述结构中,struct in_addr是使用一个uint32_t  网络字节序描述的IP地址信息,我们在转换成点分式的IP信息时,就是使用的该结构体中in_addr_t进行转换的。

1.3、结构sockaddr和结构sockaddr_in的关系

上面两节描述了通用的socket地址和以太网中使用的地址,那么,这两种结构有啥关系呢,其实,通过上面的结构体介绍,已经可以看到一个大概,sockaddr和sockaddr_in是一个同样大小的结构,其对应关系如下图:

 在sockaddr_in中,只使用了前面的8个字节,为了和sockaddr中保持结构大小一直,其后面的8个字节填充保留。

        在使用bind等相关函数时,通常都是使用的地址sockaddr,这样,我们在实际以太网编程使用的过程中,都是利用结构sockaddr_in进行地址信息的设置,然后使用强转为sockaddr类型

1.4、本地socket中使用的地址类型

在进程间通信中,也可以使用socket进行通信,与网络编程类似,其也有一个地址描述信息结构体,其结构体说明如下:

typedef unsigned short __kernel_sa_family_t;
#define UNIX_PATH_MAX	108

struct sockaddr_un {
	__kernel_sa_family_t sun_family; /* AF_UNIX */
	char sun_path[UNIX_PATH_MAX];	/* pathname */
};

其中,sun_family的取值一般使用AF_UNIX或者AF_LOCAL,sun_path是一个路径名。

二、IP地址的转换

上一章中,介绍了在网络编程中常用的几个与ip地址相关的数据结构,看完上面的一章,我们可能有这样的疑问,上面提到的IP地址都是用一个uint32_t 表示的,但是我们在实际中,见到的一般都是192.168.1.xx这种点分式的表示方法,那么,这两者之间如何转换?linux提供了一系列的函数,来完成这个工作。

  2.1 字符串IP与二进制IP地址的转换

Linux系统中提供了一组函数用于网络地址的字符串形式和二进制形式之间的转换,其形式为inet_xxx(),函数具体如下:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int inet_aton(const char *cp,struct in_addr *inp);
in_addr_t inet_addr(const char * cp);
char * inet_ntoa(struct in_addr in);

inet_aton()函数

该函数将cp中的十进制字符串类型的IP地址,转换为二进制的IP地址,转换成功后的值,保存在指向结构体 struct in_addr 中,由上一章可以知道,该结构中为 struct sockaddr_in中的一个变量。当转换成功时,返回一个非0值,当转换失败或者传入的一个非法地址时,返回值为0。

inet_addr()函数

该函数与inet_aton()函数类似,也是将字符串形式的字符串转换为二进制的IP地址,转换成功返回IP地址,这个IP地址时网络字节序的表达,如果转换失败或者参数非法,返回-1,因为-1的存储形式为(111111111111111),而IP地址255.255.255.255也是这个值,故不能使用这个函数对这个地址进行转换。

inet_ntoa()函数

该函数是将一个struct in_addr表示的一个IP地址转换为点分十进制的字符串IP地址,返回值是转换后的字符串指针,这个指针是该函数返回的,该函数会用一个静态区域保存该返回结果,有可能结果会被其他线程调用覆盖这个结果,故该函数并不是线程安全的,使用时需要注意。

2.2 IP转换函数之通用的版本

        在2.1节中,描述了常用的几个IP地址各种形式之间的转换函数,通过描述,可以知道,这几个函数或多或少存在缺陷,如只支持IPV4,或者不是线程安全的。下面介绍一对安全的与协议无关的地址转换函数,这两个函数都是可以重入支持多线程的,且这些函数支持IPv4和IPv6。

int inet_pton (int af, const char *src,void *dst);
const char *inet_ntop (int af, const void *src,char *dst, socklen_t size);

 inet_pton()函数

该函数是将字符串类型的IP地址转换为二进制类型,第一个参数af表示网络类型的协议族,在IPv4下的值为AF_INET,第二个参数src表示需要转换的字符串,第三个参数表示转换后的结构,在IPv4中,dst指向的是一个struct in_addr的结构体指针。该函数的返回值为-1的时候,通常是第一个参数af指定的协议族不支持造成的。当函数的返回值为0时,表示src指向的值不是合法的IP地址,当返回值为正值时,表示转换成功。

inet_ntop()函数

该函数是将二进制的网络IP地址转换为字符串,第一个参数af表示网络类型的协议族,在IPv4下的值为AF_INET,第二个参数src为需要转换的二进制IP地址,在IPv4中,src指向的是一个struct in_addr的结构体指针,第三个参数dst是保存结果的缓存区指针,第四个参数size是dst缓冲区的大小。当发生错误时,返回NULL,如af设置的协议族不支持,或者size参数设置的缓存区大小过小。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值