代码语言:c复制
static int sock_listen(int fd, int backlog)
{
struct socket *sock;
if (fd < 0 || fd >= NR_OPEN || current->files->fd[fd] == NULL)
return(-EBADF);
if (!(sock = sockfd_lookup(fd, NULL)))
return(-ENOTSOCK);
if (sock->state != SS_UNCONNECTED)
{
return(-EINVAL);
}
if (sock->ops && sock->ops->listen)
sock->ops->listen(sock, backlog);
// 设置socket的监听属性,accept函数时用到
sock->flags |= SO_ACCEPTCON;
return(0);
}
```
```c
static int inet_listen(struct socket *sock, int backlog)
{
struct sock *sk = (struct sock *) sock->data;
// 如果没有绑定端口则绑定一个,并把sock加到sock_array中
if(inet_autobind(sk)!=0)
return -EAGAIN;
/* We might as well re use these. */
/*
* note that the backlog is "unsigned char", so truncate it
* somewhere. We might as well truncate it to what everybody
* else does..
*/
if ((unsigned) backlog > 128)
backlog = 128;
// 设置syn 已连接队列的最大长度,在tcp.c中用到
sk->max_ack_backlog = backlog;
// 防止多次调用listen
if (sk->state != TCP_LISTEN)
{
// syn 已连接队列长度
sk->ack_backlog = 0;
sk->state = TCP_LISTEN;
}
return(0);
}
```
```c
// 绑定一个随机的端口,更新sk的源端口字段,并把sk挂载到端口对应的队列中
static int inet_autobind(struct sock *sk)
{
// 已经绑定了端口则直接返回,否则获取一个随机的端口
if (sk->num == 0)
{
sk->num = get_new_socknum(sk->prot, 0);
if (sk->num == 0)
return(-EAGAIN);
put_sock(sk->num, sk);
sk->dummy_th.source = ntohs(sk->num);
}
return 0;
}
listen函数主要的工作包括,设置socket和sock结构体的标记和状态,设置syn和已连接队列的上限。