getsockname-获取本地地址;比如,在绑定的时候设置端口号为0由系统自动选择端口绑定,或者使用了INADDR_ANY通配所有地址的情况下,后面需要用到具体的地址和端口,就可以用getsockname获取地址信息;

getpeername-获取建立连接的对端的地址和端口;

下面为源码分析:

 /*
* Get the local address ('name') of a socket object. Move the obtained
* name to user space.
*/ SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
int __user *, usockaddr_len)
{
struct socket *sock;
struct sockaddr_storage address;
int len, err, fput_needed; /* 查找socket */
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock)
goto out; err = security_socket_getsockname(sock);
if (err)
goto out_put; /* 调用socket操作的getname函数 */
err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, );
if (err)
goto out_put; /* 拷贝地址到用户空间 */
err = move_addr_to_user(&address, len, usockaddr, usockaddr_len); out_put:
fput_light(sock->file, fput_needed);
out:
return err;
}
 /*
* Get the remote address ('name') of a socket object. Move the obtained
* name to user space.
*/ SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
int __user *, usockaddr_len)
{
struct socket *sock;
struct sockaddr_storage address;
int len, err, fput_needed; /* 查找socket */
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock != NULL) {
err = security_socket_getpeername(sock);
if (err) {
fput_light(sock->file, fput_needed);
return err;
} /* 调用socket操作的getname获取对端地址,此时最后一个参数为1 */
err =
sock->ops->getname(sock, (struct sockaddr *)&address, &len,
); /* 将地址拷贝到用户空间 */
if (!err)
err = move_addr_to_user(&address, len, usockaddr,
usockaddr_len);
fput_light(sock->file, fput_needed);
}
return err;
}

ipv4情况下,getsockname和getpeername都会调用下面的inet_getname函数;

 /*
* This does both peername and sockname.
*/
int inet_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
struct sock *sk = sock->sk;
struct inet_sock *inet = inet_sk(sk);
DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr); /* 设置地址族 */
sin->sin_family = AF_INET; /* 获取对端地址 */
if (peer) {
/* 目的端口为空或者为未连接状态 */
if (!inet->inet_dport ||
((( << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) &&
peer == ))
return -ENOTCONN;
/* 设置目的端口和地址 */
sin->sin_port = inet->inet_dport;
sin->sin_addr.s_addr = inet->inet_daddr;
}
/* 获取本地地址 */
else {
/* 获取接收时ip */
__be32 addr = inet->inet_rcv_saddr; /* 不存在则获取发送时ip */
if (!addr)
addr = inet->inet_saddr; /* 设置端口和地址 */
sin->sin_port = inet->inet_sport;
sin->sin_addr.s_addr = addr;
} /* 填充部分 */
memset(sin->sin_zero, , sizeof(sin->sin_zero)); /* 设置地址长度 */
*uaddr_len = sizeof(*sin);
return ;
}
05-26 15:10