深入理解TCP/IP协议的实现之listen(基于linux1.2.13)

listen函数的逻辑比bind还简单。bind主要是校验和绑定ip、端口。listen则是修改socket的状态,并记录一些设置。

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);
}

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;

	if ((unsigned) backlog > 128)
		backlog = 128;
	// tcp接收队列的长度上限,不同系统实现不一样,具体参考tcp.c的使用
	sk->max_ack_backlog = backlog;
	// 修改socket状态,防止多次调用listen
	if (sk->state != TCP_LISTEN)
	{	
		sk->ack_backlog = 0;
		sk->state = TCP_LISTEN;
	}
	return(0);
}

// 绑定一个随机的端口,更新sk的源端口字段,并把sk挂载到端口对应的队列中,见bind函数的分析
static int inet_autobind(struct sock *sk)
{
	/* We may need to bind the socket. */
	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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值