Linux Kernel 2.6.9源码分析 -- listen

Linux Kernel 2.6.9源码分析 – listen

先来看下listen的原型:int listen(int sockfd, int backlog);
参数说明:
sockfd:要监听的socket描述字
backlog:为相应socket可以排队的最大连接个数
返回值:返回错误码
对于有链接的socket对子,系统如何来区分谁是server,谁是client呢 ?只要在创建socket的时候有调用listen接口,此socket就成为了server socket.凡是server socket都不能主动去与别的socket建立连接,而只能被动地通过accept()来接受来自client socket的请求.而client socket刚好相反,不能调用accept()来接受连接请求,而只能主动地通过connect()提出连接请求.
下面来看下系统调用sys_listen如何实现这一功能 ?

asmlinkage long sys_listen(int fd, int backlog)
{
	struct socket *sock;
	int err;
	if ((sock = sockfd_lookup(fd, &err)) != NULL) {
		if ((unsigned) backlog > sysctl_somaxconn)
			backlog = sysctl_somaxconn;
		err = security_socket_listen(sock, backlog);
		if (err) {
			sockfd_put(sock);
			return err;
		}
		err=sock->ops->listen(sock, backlog);
		sockfd_put(sock);
	}
	return err;
}

其中主要是调用sock->ops->listen,其对应的是inet_listen函数

int inet_listen(struct socket *sock, int backlog)
{
	struct sock *sk = sock->sk;
	unsigned char old_state;
	int err;
	lock_sock(sk);
	err = -EINVAL;
	if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
		goto out;
	old_state = sk->sk_state;
	if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN)))
		goto out;
	/* Really, if the socket is already in listen state
	 * we can only allow the backlog to be adjusted.
	 */
	if (old_state != TCP_LISTEN) {
		err = tcp_listen_start(sk);
		if (err)
			goto out;
	}
	sk->sk_max_ack_backlog = backlog;
	err = 0;
out:
	release_sock(sk);
	return err;
}

1.将backlog 赋值给sk->sk_max_ack_backlog
2.调用tcp_listen_start函数:
sock->tcp_opt 赋值,并将sock的状态修改:sk->sk_state = TCP_LISTEN;

int tcp_listen_start(struct sock *sk)
{
	struct inet_opt *inet = inet_sk(sk);
	struct tcp_opt *tp = tcp_sk(sk);
	struct tcp_listen_opt *lopt;

	sk->sk_max_ack_backlog = 0;
	sk->sk_ack_backlog = 0;
	tp->accept_queue = tp->accept_queue_tail = NULL;
	tp->syn_wait_lock = RW_LOCK_UNLOCKED;
	tcp_delack_init(tp);

	lopt = kmalloc(sizeof(struct tcp_listen_opt), GFP_KERNEL);
	if (!lopt)
		return -ENOMEM;

	memset(lopt, 0, sizeof(struct tcp_listen_opt));
	for (lopt->max_qlen_log = 6; ; lopt->max_qlen_log++)
		if ((1 << lopt->max_qlen_log) >= sysctl_max_syn_backlog)
			break;
	get_random_bytes(&lopt->hash_rnd, 4);

	write_lock_bh(&tp->syn_wait_lock);
	tp->listen_opt = lopt;
	write_unlock_bh(&tp->syn_wait_lock);

	/* There is race window here: we announce ourselves listening,
	 * but this transition is still not validated by get_port().
	 * It is OK, because this socket enters to hash table only
	 * after validation is complete.
	 */
	sk->sk_state = TCP_LISTEN;
	if (!sk->sk_prot->get_port(sk, inet->num)) {
		inet->sport = htons(inet->num);

		sk_dst_reset(sk);
		sk->sk_prot->hash(sk);

		return 0;  //******为何要在这里返回 ?***********
	}

	sk->sk_state = TCP_CLOSE;
	write_lock_bh(&tp->syn_wait_lock);
	tp->listen_opt = NULL;
	write_unlock_bh(&tp->syn_wait_lock);
	kfree(lopt);
	return -EADDRINUSE;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要下载 Maven 库 spring-data-build-2.6.9,可以按照以下步骤进行操作: 1. 打开 Maven 项目的 pom.xml 文件。 2. 在 `<dependencies>` 标签下添加相关依赖。具体添加的依赖如下: ``` <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-build</artifactId> <version>2.6.9</version> </dependency> ``` 3. 保存 pom.xml 文件。 Maven 会自动下载所需的依赖项,并将其存储在本地 Maven 仓库中。下载完成后,你就可以在项目中使用 spring-data-build-2.6.9 了。你可以在代码中导入相关的类,并使用它们来开发你的应用程序。 如果 Maven 无法下载该库,可以尝试以下解决方法: 1. 确认网络连接正常,确保 Maven 能够访问互联网。 2. 检查 Maven 的设置文件 settings.xml 是否正确配置,是否启用了合适的镜像源。 3. 清除本地 Maven 仓库中的缓存文件,重新下载依赖项。可以删除 Maven 仓库目录(默认位于用户目录的 .m2 文件夹)中的所有内容,然后再次构建项目。 4. 如果以上方法仍无法解决问题,可以尝试手动下载 spring-data-build-2.6.9.jar 文件,并将其安装到本地 Maven 仓库中。可以使用以下命令进行安装: ``` mvn install:install-file -Dfile=/path/to/spring-data-build-2.6.9.jar -DgroupId=org.springframework.data -DartifactId=spring-data-build -Dversion=2.6.9 -Dpackaging=jar ``` 以上就是使用 Maven 下载 spring-data-build-2.6.9 的方法和可能遇到的解决方案。希望对你有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值