zoukankan      html  css  js  c++  java
  • 套接字之 getsockname && getpeername

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

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

    下面为源码分析:

     1 /*
     2  *    Get the local address ('name') of a socket object. Move the obtained
     3  *    name to user space.
     4  */
     5 
     6 SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
     7         int __user *, usockaddr_len)
     8 {
     9     struct socket *sock;
    10     struct sockaddr_storage address;
    11     int len, err, fput_needed;
    12 
    13     /* 查找socket */
    14     sock = sockfd_lookup_light(fd, &err, &fput_needed);
    15     if (!sock)
    16         goto out;
    17 
    18     err = security_socket_getsockname(sock);
    19     if (err)
    20         goto out_put;
    21 
    22     /* 调用socket操作的getname函数 */
    23     err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
    24     if (err)
    25         goto out_put;
    26 
    27     /* 拷贝地址到用户空间 */
    28     err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
    29 
    30 out_put:
    31     fput_light(sock->file, fput_needed);
    32 out:
    33     return err;
    34 }
     1 /*
     2  *    Get the remote address ('name') of a socket object. Move the obtained
     3  *    name to user space.
     4  */
     5 
     6 SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
     7         int __user *, usockaddr_len)
     8 {
     9     struct socket *sock;
    10     struct sockaddr_storage address;
    11     int len, err, fput_needed;
    12 
    13     /* 查找socket */
    14     sock = sockfd_lookup_light(fd, &err, &fput_needed);
    15     if (sock != NULL) {
    16         err = security_socket_getpeername(sock);
    17         if (err) {
    18             fput_light(sock->file, fput_needed);
    19             return err;
    20         }
    21 
    22         /* 调用socket操作的getname获取对端地址,此时最后一个参数为1 */
    23         err =
    24             sock->ops->getname(sock, (struct sockaddr *)&address, &len,
    25                        1);
    26 
    27         /* 将地址拷贝到用户空间 */
    28         if (!err)
    29             err = move_addr_to_user(&address, len, usockaddr,
    30                         usockaddr_len);
    31         fput_light(sock->file, fput_needed);
    32     }
    33     return err;
    34 }

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

     1 /*
     2  *    This does both peername and sockname.
     3  */
     4 int inet_getname(struct socket *sock, struct sockaddr *uaddr,
     5             int *uaddr_len, int peer)
     6 {
     7     struct sock *sk        = sock->sk;
     8     struct inet_sock *inet    = inet_sk(sk);
     9     DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr);
    10 
    11     /* 设置地址族 */
    12     sin->sin_family = AF_INET;
    13 
    14     /* 获取对端地址 */
    15     if (peer) {
    16         /* 目的端口为空或者为未连接状态 */
    17         if (!inet->inet_dport ||
    18             (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) &&
    19              peer == 1))
    20             return -ENOTCONN;
    21         /* 设置目的端口和地址 */
    22         sin->sin_port = inet->inet_dport;
    23         sin->sin_addr.s_addr = inet->inet_daddr;
    24     }
    25     /* 获取本地地址 */
    26     else {
    27         /* 获取接收时ip */
    28         __be32 addr = inet->inet_rcv_saddr;
    29 
    30         /* 不存在则获取发送时ip */
    31         if (!addr)
    32             addr = inet->inet_saddr;
    33 
    34         /* 设置端口和地址 */
    35         sin->sin_port = inet->inet_sport;
    36         sin->sin_addr.s_addr = addr;
    37     }
    38 
    39     /* 填充部分 */
    40     memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
    41 
    42     /* 设置地址长度 */
    43     *uaddr_len = sizeof(*sin);
    44     return 0;
    45 }
  • 相关阅读:
    virtual pc 2007 安装ubuntuLinux出现 end trace 4eaa2a86a8e2da22 的解决办法
    关于SQLSERVER 2005的负载均衡
    华硕主板前置音频设置
    Action和Func的区别
    简单二分法 简单
    13.4 抽像类做界面(Abstract Class As Interface) 简单
    Strings_append_学习 简单
    Strings at_学习 简单
    13.6.2 新添加一种技术(Adding One Technologry) 简单
    13.3.3 应用程序界面(Application Interface) 简单
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/11749369.html
Copyright © 2011-2022 走看看