socket基础

socket

通用socket

表示socket地址的结构体sockaddr定义如下

struct sockaddr
{
    __SOCKADDR_COMMON (sa_);	//地址族类型变量
    char sa_data[14];			//socket地址值
};

不同协议族的地址值具有不同的含义和长度,有些地址值的长度可以达到108字节(PF_UNIX)。14字节的sa_data无法容纳这些协议族的地址值。因此linux定义了下面这个新的通用socket地址结构体:

#define __ss_aligntype unsigned long int
#define _SS_PADSIZE (_SS_SIZE - __SOCKADDR_COMMON_SIZE - sizeof(__ss_aligntype))
struct sockaddr_storage
{
	__SOCKADDR_COMMON (ss_);
	char __ss_padding[_SS_PADSIZE];
	__ss_aligntype __ss_align;
};

这个结构体不仅提供了足够大的空间用于存放地址值,而且是内存对齐的(__ss_align的作用)

专用socket地址

上面两个通用socket地址结构体很不好用,比如设置与获取IP地址和端口号就需要执行繁琐的位操作。所以linux为各个协议族提供了专门的socket地址结构体。

struct sockaddr_un
{
	__SOCKADDR_COMMON (sun_);	//地址族
	char sun_path[108];			//文件路径名
};

TCP/IP协议族有sockaddr_in和sockaddr_in6两个专用socket地址结构体,它们分别用于IPv4和IPv6:

#include<netinet/in.h>
struct sockaddr_in
{
	__SOCKADDR_COMMON (sin_);	//地址族
	in_port_t sin_port;			//端口号 用网络字节序表示
	struct in_addr sin_addr;	//IPv4地址结构体
	unsigned char sin_zero[sizeof(struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof(in_port_t) - sizeof(struct in_addr)];
};
struct in_addr
{
	uint32_t s_addr;			//IPv4地址,要用网络字节序表示
};

struct sockaddr_in6
{
	__SOCKADDR_COMMON (sin6_);		//地址族
	in_port_t sin6_port;			//端口号
	uint32_t sin6_flowinfo;			//流信息,应设置为0
	struct in6_addr sin6_addr;		//IPv6地址结构体
	uint32_t sin6_scope_id;			//scope ID
};

struct in6_addr
{
	uint8_t __u6_addr8[16];			//IPv6地址,使用网络字节序
};

所有专用socket地址(包括sockaddr_storage)类型的变量在实际使用时都需要转化为通用socket地址类型sockaddr(强制转换即可),因为所有socket编程接口使用的地址参数的类型都是sockaddr。

IP地址转换函数

下面三个函数可用于用点分十进制字符串表示的IPv4地址和用网络字节序整数表示的IPv4地址之间的转换:

#include<arpa/inet.h>
in_addr_t inet_addr(const char* __cp);
int inet_aton(const char *__cp,struct in_addr *__inp);
char* inet_ntoa(struct in_addr __in);

inet_addr函数将用点分十进制字符串表示的IPv4地址转化为用网络字节序整数表示的IPv4地址。失败时返回INADDR_NONE。

inet_aton函数完成和inet_addr同样的功能,但是将转化结果存储于参数inp指向的地址结构中。成功是返回1,失败时返回0。

inet_ntoa函数将用网络字节序整数表示的IPv4地址转化为用点分十进制字符串表示的IPv4地址。但是需要注意的是,该函数内部用一个静态变量存储转化结果,函数的返回值指向该静态内存,因此inet_ntoa是不可重入的。

下面这对函数也能完成和前面三个函数同样的功能,并且同时支持IPv4和IPv6:

#include<arpa/inet.h>
int inet_pton(int __af,const char *__restrict __cp,void *__restrict __buf);
const char *inet_ntop(int __af,const void *__restrict __cp,char *__restrict __buf,socklen_t __len);

inet_pton函数将用字符串表示的IP地址__cp(用点分十进制字符串表示的IPv4或是用十六进制字符串表示的IPv6地址)转化成用网络字节序整数表示的IP地址,并把转化结果存储于__buf指向的内存中。其中,af参数指定地址族,可以是AF_INET或者AF_INET6。inet_pton成功时返回1,失败时返回0并设置errno。

inet_ntop函数进行相反的转化,前三个参数的含义于inet_pton参数相同,最后一个参数__len指定目标存储单元的大小。inet_ntop成功时返回目标存储单元的地址,失败时返回NULL并设置errno。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值