• 这两个函数与域名(第9章)没有任何联系

一、概念
#include<sys/socket.h>
int getsockname(int sockfd,struct sockaddr *localaddr,socklen_t *addrlen);
int getperrname(int sockfd,struct sockaddr *perraddr,socklen_t *addrlen);
  • getsockname:用于获取本地协议地址
  • getpeername:用于获取外地协议地址

参数:

  • 参数1:套接字描述符
  • 参数2:用来保存地址信息的套接字结构体
  • 参数3:相对于参数2的结构体地址大小指针

返回值:

  • 成功:0
  • 失败:-1
二、getsockname应用场景
  • 在一个没有调用bind的TCP客户上,connect成功返回后,getsockname用于返回由内 核赋予该连接的本地IP地址和本地端口号。
  • 以端口号0调用bind(告知内核去选择本地端口号)后,getsockname用于返回由内 核赋予的本地端口号
  • getsockname可用于获取某个套接字的地址族,如下面代码所示
int
sockfd_to_family(int sockfd)
{
    struct sockaddr_storage ss;
    socklen_t len;

    len = sizeof(ss);
    if (getsockname(sockfd, (SA *) &ss, &len) < 0)
        return(-1);
    return(ss.ss_family);
} 
  •  在一个以通配IP地址调用bind的TCP服务器上,与某个客户的连接一旦建立 (accept成功返回),getsockname就可以用于返回由内核赋予该连接的本地IP地址。在这样的调用中,套接字描述符参数必须是已连接套接字的描述符,而不是监听套接字的 描述符
三、getpeername应用场景
  • 当一个服务器是由调用过accept的某个进程通过调用exec执行程序时,它能够获取客 户身份的唯一途径便是调用getpeername。inetd(13.5节)fork并exec某个TCP服务 器程序时就是如此情形,如修所示。inetd调用accept(左上方方框)返回两个值: 已连接套接字描述符connfd,这是函数的返回值;客户的IP地址及端口号,如图中标有 “对端地址”的小方框所示(代表一个网际网套接字地址结构)。inetd随后调用fork, 派生出inetd的一个子进程。既然子进程起始于父进程的内存映像的一个副本,父进程 中的那个套接字地址结构在子进程中也可用,那个已连接套接字描述符也是如此(因为 描述符在父子进程之间是共享的)。然而当子进程调用exec执行真正的服务器程序(譬 如说Telnet服务器程序)时,子进程的内存映像被替换成新的Telnet服务器的程序文件(也 就是说包含对端地址的那个套接字地址结构就此丢失),不过那个已连接套接字描述符 跨exec继续保持开放。Telnet服务器首先调用的函数之一便是getpeername,用于获取 客户的IP地址和端口号

UNP编程:05---地址获取函数(getsockname、getpeername)_套接字

四、演示案例
int sockfd=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_storage ss;
socklen_t len;
len=sizeof(ss);

if(getsockname(sockfd,(struct sockaddr*)&ss,&len)<0)
    return -1;
  • 既然不知道要分配的套接字地址结构的类型,我们于是采用sockaddr_storage这个通 用结构,因为它能够承载系统支持的任何套接字地址结构