目录
sock_ntop和相关函数
- inet_ntop存在一个问题:
- 它要求调用者传递一个指向某个二进制地址的指针,而该地址通常包含在一个套接字地址结构中,这就要求调用者必须知道这个结构的格式和地址族。
- 为了使用这个函数,必须为IPv4编写如下代码:
struct sockaddr_in addr; inet_ntop(AF_INET, &addr.sin_addr, str, sizeof(str));
- 或为IPv6编写如下代码:
struct sockaddr_in6 addr6; inet_ntop(AF_INET6, &addr6.sin6_addr, str, sizeof(str));
- 这就使得代码与协议相关。
- 编写一个名为sock_ntop的函数
- 它以指向某个套接字地址结构的指针为参数,查看该结构的内部,然后调用适当的函数返回该地址的表达格式。
#include "unp.h" char *sock_ntop(const struct sockaddr *sockaddr, socklen_t addrlen);
- 返回:
- 若成功则为非空指针,若出错则为NULL
- sockaddr指向一个长度为addrlen的套接字地址结构
- 本函数用它自己的静态缓冲区来保存结果,指向该缓冲区的一个指针就是它的返回值。
- 注意:对结果进行静态存储导致该函数不可重入且非线程安全
- 表达格式就是在一个IPv4地址的点分十进制数串格式之后,或者在一个括以方括号的IPv6地址的十六进制数串格式之后,跟一个终止符(我们使用一个分号,类似于URL语法),再跟一个十进制的端口号,最后跟一个空字符。
- 缓冲区大小对于IPv4至少为INET_ADDRSTRLEN加上6个字节(16+6=22),对于IPv6至少为INET6_ADDRSTRLEN加上8个字节(46+8=54)。
#include "unp.h" #ifdef HAVE_SOCKADDR_DL_STRUCT #include <net/if_dl.h> #endif /* include sock_ntop */ char * sock_ntop(const struct sockaddr *sa, socklen_t salen) { char portstr[8]; static char str[128]; /* Unix domain is largest */ switch (sa->sa_family) { case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in *) sa; if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) return(NULL); if (ntohs(sin->sin_port) != 0) { snprintf(portstr, sizeof(portstr), ":%d", ntohs(sin->sin_port)); strcat(str, portstr); } return(str); } /* end sock_ntop */ #ifdef IPV6 case AF_INET6: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; str[0] = '['; if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + 1, sizeof(str) - 1) == NULL) return(NULL); if (ntohs(sin6->sin6_port) != 0) { snprintf(portstr, sizeof(portstr), "]:%d", ntohs(sin6->sin6_port)); strcat(str, portstr); return(str); } return (str + 1); } #endif }
- 还为操作套接字地址结构定义了其他几个函数,它们将简化我们的代码在IPv4与IPv6之间的移植
- sock_bind_wild
- 将通配地址和一个临时端口捆绑到一个套接字
int sock_bind_wild(int sockfd, int family);
- 返回:若成功则为0,若出错则为-1
- sock_cmp_addr
- 比较两个套接字地址结构的地址部分
int sock_cmp_addr(const struct sockaddr *sockaddr1,const struct sockaddr *sockaddr2, socklen_t addrlen);
- 返回:若地址为同一协议族且相同则为0,否则为非0
- sock_cmp_port
- 比较两个套接字地址结构的端口号部分
int sock_cmp_port(const struct sockaddr *sockaddr1,const struct sockaddr *sockaddr2, socklen_t addrlen);
- 返回:若地址为同一协议族且端口相同则为0,否则为非0
- sock_get_port
- 只返回端口号
int sock_get_port(const struct sockaddr *sockaddr, socklen_t addrlen);
- 返回:若为IPv4或IPv6地址则为非负端口号,否则为-1
- sock_ntop_host
- 把一个套接字地址结构中的主机部分转换成表达格式(不包括端口号)
char *sock_ntop_host(const struct sockaddr *sockaddr, socklen_t addrlen);
- 返回:若成功则为非空指针,若出错则为NULL
- sock_set_addr
- 把一个套接字地址结构中的地址部分置为ptr指针所指的值
void sock_set_addr(const struct sockaddr *sockaddr, socklen_t addrlen, void* ptr);
- sock_set_port
- 只设置一个套接字地址结构的端口号部分
void sock_set_port(const struct sockaddr *sockaddr, socklen_t addrlen, int port);
- sock_set_wild
- 把一个套接字地址结构中的地址部分置为通配地址。
void sock_set_wild(struct sockaddr *sockaddr, socklen_t addrlen);
- 为那些返回值不是void的上述函数提供了包裹函数,它们的名字以S开头,程序通常调用这些包裹函数。
- 【注】参考《UNIX网络编程》
《UNIX网络编程》阅读笔记:sock_ntop和相关函数
最新推荐文章于 2023-05-05 00:06:33 发布