套接口地址结构-ipv4
程序员文章站
2024-02-14 15:13:16
...
引言:不知道大家又没有遇到过这种情况,就是比如我想打印根据连接套接字打印点分形式的ip地址(如127.0.0.1),我知道我应该调用inet_ntoa(),然后去看man手册,是这样的:
char *inet_ntoa(struct in_addr in);
然后我知道我应该传一个struct in_addr
的结构体
/* Internet address. */
typedef uint32_t in_addr_t;
struct in_addr
{
in_addr_t s_addr;
};
那么struct in_addr
我又应该怎么获取呢,它又包含在哪个结构体里面呢??
我决定停下手头的工作,翻开《unix网络编程 卷一》重温一下相关章节
1. 套接口地址结构 -->见《unix网络编程 卷一》3.2节
1.1 IPv4套接口地址结构
- 也叫网际套接口地址结构,以
sockaddr_in
命名,定义在 <netinet/in.h>/* 网际套接口地址结构. */ typedef uint32_t in_addr_t; struct in_addr { in_addr_t s_addr; };
- in_addr_t inet_addr(const char *cp);
- char *inet_ntoa(struct in_addr in);
- 网络套接字地址
struct sockaddr_in { __SOCKADDR_COMMON (sin_);/* sa_family_t sa_prefix##family --> unsigned short */ in_port_t sin_port; /* uint16_t --> unsigned short */ struct in_addr sin_addr; /* __be32 s_addr; --> unsigned int */ unsigned char sin_zero[8];/* 保持与 `struct sockaddr' 大小一致 */ };
- 通用套接口地址结构
struct sockaddr { __SOCKADDR_COMMON (sa_);/* sa_family_t sa_prefix##family --> unsigned short */ char sa_data[14]; /* Address data. */ };
-
为什么有这么个东西?因为套接口函数的定义出现在ANSI C之前,那时候没有void类型
,从内核的角度看,需要依据调用者的指针,将其转换为 struct sockaddr *,然后检查sa_family来确定结构类型 - int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
-
2.小结
如 3.2节所述,之所以引入struct sockaddr
是为了兼容性,所以对于开头的问题,我们可以这样写:
struct sockaddr_in sa;
int len = sizeof(sa);
if(!getpeername(sockfd, (struct sockaddr *)&sa, &len)){
printf( "remote IP[%s],port[%d]\n", inet_ntoa(sa.sin_addr),ntohs(sa.sin_port));
}