您的位置:首页 > 编程语言

3章 套接字编程简介

2017-10-25 21:46 309 查看
套接字编程都会用到套接字地址,这里讲述一些基本的系统调用函数,非常的简单,这里可以好好思考。调用函数给被调用函数分配空间,然后传递指针给调用函数填充结构空间。

套接字地址结构

用于存储当前连接的一些关键信息。

#define __SOCKADDR_COMMON(sa_prefix) \
sa_family_t sa_prefix##family
struct in_addr
{
in_addr_t s_addr;
};
//IPv4套接字地址结构,在使用结构之前必须置0
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);    /* 套接字地址结构的地址族 AF_INET */
in_port_t sin_port;          /* TCP或UDP端口号  */
struct in_addr sin_addr;     /* IPV4地址  */

/* Pad to size of `struct sockaddr'. 未使用字段 */
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
/*
通用套接字地址,传递给socket,listen等等的参数类型。
正常为了处理任何类型,应该是void *指针,但是socket在通用指针定义出现之前,所以采用了sockaddr的方向,去读取第一个成员区分类型。所以将sockaddr_in和sockaddr_in6地址传入都必须进行强制转换为struct sockaddr *类型。
*/
struct sockaddr
{
__SOCKADDR_COMMON (sa_);    /* Common data: address family and length.  */
char sa_data[14];       /* Address data.  */
};

//IPv6套接字地址结构,用的较少,了解即可。
struct sockaddr_in6
{
__SOCKADDR_COMMON (sin6_);/* 地址族 AF_INET6  */
in_port_t sin6_port; /* Transport layer port # */
uint32_t sin6_flowinfo;  /* IPv6 flow information */
struct in6_addr sin6_addr;   /* IPv6 address */
uint32_t sin6_scope_id;  /* IPv6 scope-id */
};
//上述地址结构仅仅为了记录当前连接的端口以及IP地址信息,供进程调用。




值-结果参数

数据结构里面包含其长度,当进程传递数据都内核时候,传递数据结构指针,因为里面含有长度,所以内核填充结构不至于内存越界这就是值传递。当内核传递数据到进程,返回长度信息,内核可以告诉进程内核究竟存储了多少信息。上述过程称为值-结果参数。



字节排序函数

大端模式,小端模式,系统硬件不同存储数据字节序列不同。

网络协议因为一次性传递一系列字节,所以规范指定一个网络字节序,网络协议使用大端字节序来传送多字节数据,也就是先传送高字节。只要接收方和发送方都使用网络字节序传递,数据就不会错。

/*
h = host    主机字节序(大端或小段)
n = network 网络字节序(大端)
s = short
l = long
这些函数屏蔽了系统直接的差异,假如主机字节序本来就是大端模式,那么这些函数都是空定义。
*/
uint32_t ntohl (uint32_t __netlong);
uint16_t ntohs (uint16_t __netshort);//返回主机字节序
uint32_t htonl (uint32_t __hostlong);
uint16_t htons (uint16_t __hostshort);//返回网络字节序


字节操纵函数

//将对应字节对应长度全部清0
void __bzero (void *__s, size_t __n);//将目标字节串指定数目置0,用于初始化套接字地址 类似memset。
void bcopy (const void *__src, void *__dest, size_t __n);
int bcmp (const void *__s1, const void *__s2, size_t __n);


地址转换函数

///////////////////仅仅适用于IPV4的地址转换函数///////////////////////
/*
将cp中形如"206.168.112.68"类似的点分十进制IP地址字符串转换成32位网络字节序二进制数。存储在__inp中,成功返回1,失败0.
*/
int inet_aton (const char *__cp, struct in_addr *__inp);

/*
将32位网络字节序二进制转换成点分十进制。
因为返回一个地址,所以,函数内部必须使用static才可以保存返回值,否则函数退出即销毁。
返回值指向的字符串驻留在静态内存中。所以该函数不可重入。
参数是结构,全部复制进栈,开销非常大,为什么这样么?这就需要问当初写源代码的人了。
*/
char *inet_ntoa (struct in_addr __in);

///////////////////适用于IPV4和IPV6的地址转换函数///////////////////////
/*
p=presentation表达,地址表达为字符串。
n=numeric 数值为二进制值。
地址二者相互转换函数,支持IPV4和IPV6.
__af:指定协议类型
AF_INET 用于IPV4协议
AF_INET6 用于IPV6协议
__cp:存放点分十进制字符串,inet_ntop 中不可为空,内存都由调用者分配用来存放转换结果,成功返回内存首地址。
__buf:存放转换结果的地方
__len:指定目标单元大小,防止溢出调用者缓冲区。
*/
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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: