zoukankan      html  css  js  c++  java
  • 套接字之listen系统调用

    对于面向连接的socket,需要会用监听连接的到来,并且使用backlog参数来限制连接数量;具体backlog限制的内容,请参考本博另外一篇文章,本文结尾提供链接地址;

     1 /*
     2  *    Perform a listen. Basically, we allow the protocol to do anything
     3  *    necessary for a listen, and if that works, we mark the socket as
     4  *    ready for listening.
     5  */
     6 
     7 SYSCALL_DEFINE2(listen, int, fd, int, backlog)
     8 {
     9     struct socket *sock;
    10     int err, fput_needed;
    11     int somaxconn;
    12 
    13     /* 查找socket结构 */
    14     sock = sockfd_lookup_light(fd, &err, &fput_needed);
    15     if (sock) {
    16         somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
    17 
    18         /* backlog不能超过设置值 */
    19         if ((unsigned int)backlog > somaxconn)
    20             backlog = somaxconn;
    21 
    22         /* 安全模块检查 */
    23         err = security_socket_listen(sock, backlog);
    24         if (!err)
    25             /* 调用对应类型的listen函数,只有SOCK_STREAM支持listen */
    26             err = sock->ops->listen(sock, backlog);
    27 
    28         fput_light(sock->file, fput_needed);
    29     }
    30     return err;
    31 }

    inet_listen、数对socket类型,连接状态等进行基本的校验,如果已经处于listen状态,则只会调整backlog的值,如果尚未处于listen状态,则调用传输层的listen实现函数进行针对的listen操作;

     1 /*
     2  *    Move a socket into listening state.
     3  */
     4 int inet_listen(struct socket *sock, int backlog)
     5 {
     6     struct sock *sk = sock->sk;
     7     unsigned char old_state;
     8     int err;
     9 
    10     lock_sock(sk);
    11 
    12     err = -EINVAL;
    13 
    14     /* 检查socket状态和类型,仅支持SOCK_STREAM */
    15     if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
    16         goto out;
    17 
    18     /* 记录连接当前状态 */
    19     old_state = sk->sk_state;
    20 
    21     /* 检查连接状态,需为close或者listen */
    22     if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN)))
    23         goto out;
    24 
    25     /* Really, if the socket is already in listen state
    26      * we can only allow the backlog to be adjusted.
    27      */
    28     /* 如果尚未listen过 */
    29     if (old_state != TCP_LISTEN) {
    30         /* Enable TFO w/o requiring TCP_FASTOPEN socket option.
    31          * Note that only TCP sockets (SOCK_STREAM) will reach here.
    32          * Also fastopen backlog may already been set via the option
    33          * because the socket was in TCP_LISTEN state previously but
    34          * was shutdown() rather than close().
    35          */
    36         /* TFO相关*/
    37         if ((sysctl_tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) &&
    38             (sysctl_tcp_fastopen & TFO_SERVER_ENABLE) &&
    39             !inet_csk(sk)->icsk_accept_queue.fastopenq.max_qlen) {
    40             fastopen_queue_tune(sk, backlog);
    41             tcp_fastopen_init_key_once(true);
    42         }
    43 
    44         /* 开始监听 */
    45         err = inet_csk_listen_start(sk, backlog);
    46         if (err)
    47             goto out;
    48     }
    49 
    50     /* 设置backlog,包括已经listen过,调整backlog */
    51     sk->sk_max_ack_backlog = backlog;
    52     err = 0;
    53 
    54 out:
    55     release_sock(sk);
    56     return err;
    57 }
    58 EXPORT_SYMBOL(inet_listen);

    其中tcp层对于listen的实现,实际上也是调用了inet_csk_get_port函数,与bind()系统调用在tcp层的调用函数一致,listen的时候,如果发现尚未绑定端口,则自动选择端口绑定,已经绑定端口,则进行相关检查;具体请参考bind()系统调用的tcp层实现;请阅读<TCP层bind系统调用的实现分析>;

    关于TCP的listen函数和backlog参数说明,请移步以下文章<TCP之listen&backlog>;

  • 相关阅读:
    JS仿淘宝网顶部的导航菜单
    JS+CSS打造高仿XP默认主题菜单样式
    Jquery打造网页右上角可伸缩关闭的菜单
    来自百度百科的目录显示/隐藏效果
    Jquery打造的下拉层式菜单
    javascript小數位四舍五入[IE5.5+]
    css外容器margin問題[IE中height:100%]
    EXEC执行动态SQL时取出变量值[EXEC函数只能是局部变量]
    sql一列变多列
    判斷日期,輸出成YYYY/MM/DD形式
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/7618389.html
Copyright © 2011-2022 走看看