套接字编程

套接字编程

1. 套接字地址结构

1.1 IPv4套接字地址结构

<netinet/in.h>

struct in_addr
{
    in_addr_t s_addr;   /* 32-bit IPv4 address */
                        /* network byte ordered */
};

struct sockaddr_in
{
    uint8_t       sin_len;        /* length of struct */
    sa_family_t   sin_family;     /* AF_INET */
    in_port_t     sin_port;       /* 16-bit TCP or UDP port number */
                                  /* network byte ordered */
    struct in_addr  sin_addr;     /* 32-bit IPv4 address */
                                  /* network byte ordered */
    char            sin_zero[8];  /* unused */
};

1.2 通用套接字地址结构

当作为一个参数传递进任何套接字函数时,套接字地址结构总是以引用形式(也就是以指向该结构的指针)来传递。

通用套接字地址结构
#include <sys/socket.h>

struct sockaddr
{
    uint8_t         sa_len;
    sa_family_t     sa_family;   /* address family: AF_XXX value */
    char            sa_data[14]; /* protocol-specific address */
};

1.3 IPv6 套接字地址结构

#include <netinet/in.h>

struct in6_addr
{
    unit8_t s6_addr[16]; /* 128-bit IPv6 address */
                         /* network byte ordered */
};

#define SIN6_LEN   /* required for compile-time tests */

struct sockaddr_in6
{
    uint8_t     sin6_len;       /* length of this struct (28) */
    sa_family_t sin6_family;    /* AF_INET6 */
    in_port_t   sin6_port;      /* transport layer port# */
                                /* network byte ordered */
    uint32_t    sin6_flowinfo;  /* flow information, undefined */
    struct in6_addr  sin6_addr; /* IPv6 address */
                                /* network byte ordered */
    uint32_t    sin6_scope_id;  /* set of interfaces for a scope */

};

1.4 新的通用套接字地址结构

#include <sys/in.h>

struct sockaddr_storage
{
    uint8_t     ss_len;     /* length of this struct */
    sa_family_t ss_family;  /* address family: AF_xxx value */
    ...
};

2. 值-结果参数

当往一个套接字函数传递一个套接字地址结构时,该结构总是以引用形式来传递,也就是说传递的是指向该结构的一个指针。该结构的长度也作为一个参数来传递。

  1. 从进程到内核传递套接字地址结构的函数有 3 个:bind、connect、sendto 。
  2. 从内核到进程传递套接字地址结构的函数有 4 个:accept、recvfrom、getsockname、getpeername 。

当函数被调用时,结构大小是一个值,它告诉内核该结构的大小,这样内核在写该结构时不至于越界;当函数返回时,结构大小又是一个结果,它告诉进程内核在该结构中究竟存储了多少信息。

这种类型的参数称为 值-结果 参数。

3. 字节排序函数

小端和大端表示多个字节值的哪一端(小端或大端)存储在该值的起始地址。

把某个给定系统所用的字节序称为主机字节序
网路协议必须指定一个网络字节序网际协议使用大端字节序来传送这些多字节整数

使用如下 4 个函数,在主机字节序和网络字节序之间相互转换。

#include <netinet/in.h>

//返回:网络字节序的值
uint16_t htons(uint16_t host16bitvalue);

uint32_t htonl(uint32_t host32bitvalue);

//返回:主机字节序的值
uint16_t ntohs(uint16_t net16bitvalue);

uint32_t ntohl(uint32_t net32bitvalue);

h 代表 host,n 代表 netwok,s 代表 short,l 代表 long。

4. inet_aton、inet_ntoa 函数

点分十进制数串(例 206.168.112.96)与它长度为 32 位的网络字节序二进制值间转换 IP 地址。

#include <arpa/inet.h>

//返回:若字符串有效则为 1,否则为 0
int inet_aton(const char *strptr, struct in_addr *addrptr);

//返回:指向一个点分十进制数串的指针
char *inet_ntoa(struct in_addr inaddr);

inet_aton 将 strptr 所指 C 字符串转换成一个 32 位的网络字节序二进制值。
inet_ntoa 将一个 32 位的网络字节序二进制 IPv4 地址转换成相应的点分十进制数串。

5. inet_pton、inet_ntop 函数

这两个函数是随 IPv6 出现的新函数,对于 IPv4 和 IPv6 都适用。

函数名中 p 和 n 分别代表 表达(presentation)和 数值(numeric)。地址的表达格式通常是 ASCII 字符串,数值格式则是存放到套接字地址结构中的二进制值。

#include <arpa/inet.h>

//返回:若成功则为 1 ;若输入不是有效的表达格式则为 0;若出错则为 -1
int inet_pton(int family, const char *strptr, void *addrptr);

//返回:若成功则为指向结果的指针;若出错则为 NULL
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);

family 参数既可以是 AF_INET,也可以是 AF_INET6 。

inet_pton 函数尝试转换由 strptr 指针所指向的字符串,并通过 addrptr 指针存放二进制结果。
inet_ntop 函数进行相反的转换,从数值格式转换到表达格式。len参数是目标存储单元的大小。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值