7-socket的实践到内核--socket的监听 .

http://blog.csdn.net/embeddedfly/article/details/6411735

这节我们看一下服务器端的socket监听,还是从应用程序界面看起

listen(server_sockfd, 5);

中间的过程我们不说了,只说到达了函数sys_listen()处,不知道这个过程的朋友参考前面几节内容。这个函数在/net/socket.c中的1370行处。

asmlinkagelong sys_listen(int fd,int backlog)
{
    struct socket*sock;
    int err, fput_needed;
    int somaxconn;

    sock = sockfd_lookup_light(fd,&err, &fput_needed);
    if (sock){
        somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
        if ((unsigned)backlog> somaxconn)
            backlog = somaxconn;

        err = security_socket_listen(sock, backlog);
        if (!err)
            err = sock->ops->listen(sock, backlog);

        fput_light(sock->file, fput_needed);
    }
    return err;
}

sockfd_lookup_light()函数我们在前边看到过了,我们同时比照一下sys_listen()与sys_bind()函数的差别,发现基本相同,只不同的地方就是

sock->ops->listen(sock, backlog);

这里可以看一下我们以前提到的unix的二个结构

staticconst struct proto_ops unix_stream_ops

staticconst struct proto_ops unix_dgram_ops

这里我们的socket是使用的第一个unix_stream_ops即tcp有连接的socket,可以看到这个结构中

    .listen=    unix_listen,

因此我们上面的sys_listen()会执行unix_listen这个钩子函数,我们看一下,这个函数在/net/unix/Af_unix.c中的451行处

staticint unix_listen(structsocket *sock,int backlog)
{
    int err;
    struct sock *sk= sock->sk;
    struct unix_sock *u = unix_sk(sk);

    err = -EOPNOTSUPP;
    if (sock->type!=SOCK_STREAM&& sock->type!=SOCK_SEQPACKET)
        goto out;            /* Only stream/seqpacket sockets accept */
    err = -EINVAL;
    if (!u->addr)
        goto out;            /* No listens on an unbound socket */
    unix_state_lock(sk);
    if (sk->sk_state!= TCP_CLOSE&& sk->sk_state!= TCP_LISTEN)
        goto out_unlock;
    if (backlog> sk->sk_max_ack_backlog)
        wake_up_interruptible_all(&u->peer_wait);
    sk->sk_max_ack_backlog    = backlog;
    sk->sk_state        = TCP_LISTEN;
    /* set credentials so connect can copy them */
    sk->sk_peercred.pid    = task_tgid_vnr(current);
    sk->sk_peercred.uid    = current->euid;
    sk->sk_peercred.gid    = current->egid;
    err = 0;

out_unlock:
    unix_state_unlock(sk);
out:
    return err;
}

从上文的注释中我们也可以看出,这里只支持有连接的socket,并且我们也可以看出上边有一个sk_state用来判断sock的状态,同时我们也看到if (!u->addr)没有绑定地址的socket不允许监听,接下来,判断一下要监听的队列个数,这是从我们的应用程序传递下来的5个连接,所以如果这个链接大于sock的最大连接数就要唤醒在socket中睡眠等待连接的进程,让他们有机会与服务器端的socket连接成功。我们以前在练习中看到,listen()界面是用在服务器端的socket一侧的,所以,这里将服务器端的进程号以及状态设置为TCP_LISTEN,将来客户端在connect()请求连接并经服务器端的accept()同意连接后,就会获得这里的服务器端的sock中关于服务进程的信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值