网络中的listen
Posted 为了维护世界和平_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络中的listen相关的知识,希望对你有一定的参考价值。
listen主要工作
申请和初始化接收队列,全连接接收队列和半接收队列
int __sys_listen(int fd, int backlog)
struct socket *sock;
int err, fput_needed;
int somaxconn;
//根据fd查找socket内核对象
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock)
//获取内核somaxconn参数;net.core.somaxconn,与backlog 取其中小的
somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
if ((unsigned int)backlog > somaxconn)
backlog = somaxconn;
err = security_socket_listen(sock, backlog);
if (!err)//调用协议栈初始化listen
err = sock->ops->listen(sock, backlog);
fput_light(sock->file, fput_needed);
return err;
backlog与系统里的net.core.somaxconn内核参数选择一个小的
sock->ops->listen函数
int inet_listen(struct socket *sock, int backlog)
struct sock *sk = sock->sk;
unsigned char old_state;
int err, tcp_fastopen;
//如果是监听状态,则允许backlog参数调整,设置全连接队列长度
WRITE_ONCE(sk->sk_max_ack_backlog, backlog);
//不是listen状态,进入监听
if (old_state != TCP_LISTEN)
tcp_fastopen = sock_net(sk)->ipv4.sysctl_tcp_fastopen;
if ((tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) &&
(tcp_fastopen & TFO_SERVER_ENABLE) &&
!inet_csk(sk)->icsk_accept_queue.fastopenq.max_qlen)
fastopen_queue_tune(sk, backlog);
tcp_fastopen_init_key_once(sock_net(sk));
//开始监听
err = inet_csk_listen_start(sk, backlog);
if (err)
goto out;
tcp_call_bpf(sk, BPF_SOCK_OPS_TCP_LISTEN_CB, 0, NULL);
err = 0;
out:
release_sock(sk);
return err;
全连接队列结构体
struct inet_connection_sock
/* inet_sock has to be the first member! */
struct inet_sock icsk_inet;
struct request_sock_queue icsk_accept_queue;
...
struct request_sock_queue
spinlock_t rskq_lock;
u8 rskq_defer_accept;
u32 synflood_warned;
atomic_t qlen;
atomic_t young;
//全连接队列
struct request_sock *rskq_accept_head;
struct request_sock *rskq_accept_tail;
struct fastopen_queue fastopenq; /* Check max_qlen != 0 to determine
* if TFO is enabled.
*/
;
int inet_csk_listen_start(struct sock *sk, int backlog)
struct inet_connection_sock *icsk = inet_csk(sk);
struct inet_sock *inet = inet_sk(sk);
int err = -EADDRINUSE;
//icsk_accept_queue接收队列
//接收队列内核对象初始化
reqsk_queue_alloc(&icsk->icsk_accept_queue);
sk->sk_ack_backlog = 0;
inet_csk_delack_init(sk);
inet_sk_state_store(sk, TCP_LISTEN);
if (!sk->sk_prot->get_port(sk, inet->inet_num))
inet->inet_sport = htons(inet->inet_num);
sk_dst_reset(sk);
err = sk->sk_prot->hash(sk);
if (likely(!err))
return 0;
inet_sk_set_state(sk, TCP_CLOSE);
return err;
static inline void fastopen_queue_tune(struct sock *sk, int backlog)
struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
int somaxconn = READ_ONCE(sock_net(sk)->core.sysctl_somaxconn);
//半连接队列长度
queue->fastopenq.max_qlen = min_t(unsigned int, backlog, somaxconn);
总结:listen主要工作申请和初始化接收队列,全连接接收队列和半接收队列
全连接接收队列长度
backlog与net.core.somaxconn之间较小的值
以上是关于网络中的listen的主要内容,如果未能解决你的问题,请参考以下文章
网络连接返回getsockopt: connection refused错误原因 及 listen
Oracle数据库学习_Oracle监听程序LISTENER和网络服务名Tnsname