《UNIX网络编程》阅读笔记:sock_ntop和相关函数

目录

sock_ntop和相关函数


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网络编程》
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值