返回顶部
首页 > 资讯 > 操作系统 >怎么从Linux源码看Socket TCP的Listen及连接队列
  • 783
分享到

怎么从Linux源码看Socket TCP的Listen及连接队列

2023-06-15 19:06:55 783人浏览 薄情痞子
摘要

怎么从linux源码看Socket tcp的Listen及连接队列,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。从Linux源码看Socket(TCP)的lis

怎么从linux源码Socket tcp的Listen及连接队列,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

从Linux源码看Socket(TCP)的listen及连接队列前言笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情。今天笔者就来从Linux源码的角度看下Server端的Socket在进行listen的时候到底做了哪些事情(基于Linux  3.10内核),当然由于listen的backlog参数和半连接hash表以及全连接队列都相关,在这一篇博客里也一块讲了。

Server端Socket需要Listen

众所周知,一个Server端Socket的建立,需要socket、bind、listen、accept四个步骤。今天笔者就聚焦于Listen这个步骤。

怎么从Linux源码看Socket TCP的Listen及连接队列

代码如下:

void start_server(){     // server fd     int sockfd_server;     // accept fd      int sockfd;     int call_err;     struct sockaddr_in sock_addr;   ......     call_err=bind(sockfd_server,(struct sockaddr*)(&sock_addr),sizeof(sock_addr));     if(call_err == -1){         fprintf(stdout,"bind error!\n");         exit(1);     }     // 这边就是我们今天的聚焦点listen     call_err=listen(sockfd_server,MAX_BACK_LOG);     if(call_err == -1){         fprintf(stdout,"listen error!\n");         exit(1);     } }

首先我们通过socket系统调用创建了一个socket,其中指定了SOCK_STREAM,而且最后一个参数为0,也就是建立了一个通常所有的TCP  Socket。在这里,我们直接给出TCP Socket所对应的ops也就是操作函数。

怎么从Linux源码看Socket TCP的Listen及连接队列

如果你想知道上图中的结构是怎么来的,可以看下笔者以前的博客:

https://my.oschina.net/alchemystar/blog/1791017

Listen系统调用好了,现在我们直接进入Listen系统调用吧。

#include <sys/socket.h> // 成功返回0,错误返回-1,同时错误码设置在errno int listen(int sockfd, int backlog);

注意,这边的listen调用是被glibc的INLINE_SYSCALL装过一层,其将返回值修正为只有0和-1这两个选择,同时将错误码的绝对值设置在errno内。这里面的backlog是个非常重要的参数,如果设置不好,是个很隐蔽的坑。

对于java开发者而言,基本用的现成的框架,而java本身默认的backlog设置大小只有50。这就会引起一些微妙的现象,这个在本文中会进行讲解。

怎么从Linux源码看Socket TCP的Listen及连接队列

接下来,我们就进入Linux内核源码栈吧

listen  |->INLINE_SYSCALL(listen......)   |->SYSCALL_DEFINE2(listen, int, fd, int, backlog)      // 在开启SYN cookie的情况下,如果半连接队列长度超过backlog,则发送cookie  // 否则丢弃  if (inet_csk_reqsk_queue_is_full(sk) && !isn) {   want_cookie = tcp_syn_flood_action(sk, skb, "TCP");   if (!want_cookie)    Goto drop;  }     // 在全连接队列满的情况下,如果有young_ack,那么直接丢弃  if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {   NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);   goto drop;  }

我们在dmesg里面经常看到的

Possible SYN flooding on port 8080

就是由于半连接队列满以后,Kernel发送cookie校验而导致。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网操作系统频道,感谢您对编程网的支持。

--结束END--

本文标题: 怎么从Linux源码看Socket TCP的Listen及连接队列

本文链接: https://lsjlt.com/news/281441.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作