listen函数只能被SOCK_STREAM类型的服务器调用,listen提供两个功能,
第一当套接字由套接字函数创建时,它被认为是活动的套接字,即将发出连接的客户端套接字。 监听功能将未连接的套接字转换为被动套接字,指示该套接字内核应该接受传入此套接字的连接请求。 在TCP状态转换图的中,调用listen将套接字从CLOSED状态移动到LISTEN状态。
第二listen的第二个参数指定套接字上可以排队等待的连接数的最大值,超过最大值时,套接字将拒绝新的连接请求
内核listen系统调用
-
SYSCALL_DEFINE2(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 int)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;
-
}
调用的是unix_listen
-
static int unix_listen(struct socket *sock, int backlog)
-
{
-
int err;
-
struct sock *sk = sock->sk;
-
struct unix_sock *u = unix_sk(sk);
-
struct pid *old_pid = NULL;
-
-
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 */
-
init_peercred(sk);
-
err = 0;
-
-
out_unlock:
-
unix_state_unlock(sk);
-
put_pid(old_pid);
-
out:
-
return err;
-
}
进入监听状态之后就可以接收客户端的连接了。
阅读(1890) | 评论(0) | 转发(0) |