1.从Linux源码看Socket(TCP)的握手握手listen及连接队列
2.一文了解Linux上TCP的几个内核参数调优
3.详细讲解Linux内核角度分析tcpdump原理(1)
4.如何测量和确定linux系统中tcp初始发送窗口的大小?
5.linux下安装tcpdump并用其抓包
6.ç
è°linuxä¸TCPï¼ä¸ï¼
从Linux源码看Socket(TCP)的listen及连接队列
了解Linux内核中Socket (TCP)的"listen"及连接队列机制是深入理解网络编程的关键。本文将基于Linux 3.内核版本,源码从源码角度解析Server端Socket在进行"listen"时的握手握手具体实现。
建立Server端Socket需要经历socket、源码bind、握手握手listen、源码ap 底层源码accept四个步骤。握手握手本文聚焦于"listen"步骤,源码深入探讨其内部机理。握手握手
通过socket系统调用,源码我们可以创建一个基于TCP的握手握手Socket。这里直接展示了与TCP Socket相关联的源码操作函数。
接着,握手握手我们深入到"listen"系统调用。源码注意,握手握手glibc的INLINE_SYSCALL对返回值进行了封装,仅保留0和-1两种结果,并将错误码的绝对值记录在errno中。其中,backlog参数至关重要,设置不当会引入隐蔽的陷阱。对于Java开发者而言,框架默认backlog值较小(默认),这可能导致微妙的行为差异。
进入内核源码栈,我们发现内核对backlog值进行了调整,限制其不超过内核参数设置的somaxconn值。
核心调用程序为inet_listen。其中,除了fastopen外的逻辑(fastopen将在单独章节深入讨论)最终调用inet_csk_listen_start,将sock链入全局的listen hash表,实现对SYN包的高效处理。
值得注意的是,SO_REUSEPORT特性允许不同Socket监听同一端口,实现内核级的负载均衡。Nginx 1.9.1版本启用此功能后,性能提升3倍。udx 源码
半连接队列与全连接队列是连接处理中的关键组件。通常提及的sync_queue与accept_queue并非全貌,sync_queue实际上是syn_table,而全连接队列为icsk_accept_queue。在三次握手过程中,这两个队列分别承担着不同角色。
在连接处理中,除了qlen与sk_ack_backlog计数器外,qlen_young计数器用于特定场景下的统计。SYN_ACK的重传定时器在内核中以ms为间隔运行,确保连接建立过程的稳定。
半连接队列的存在是为抵御半连接攻击,避免消耗大量内存资源。通过syn_cookie机制,内核能有效防御此类攻击。
全连接队列的最大长度受到限制,超过somaxconn值的连接会被内核丢弃。若未启用tcp_abort_on_overflow特性,客户端可能在调用时才会察觉到连接被丢弃。启用此特性或增大backlog值是应对这一问题的策略。
backlog参数对半连接队列容量产生影响,导致内核发送cookie校验时出现常见的内存溢出警告。
总结而言,TCP协议在数十年的演进中变得复杂,深入阅读源码成为分析问题的重要途径。本文深入解析了Linux内核中Socket (TCP)的"listen"及连接队列机制,旨在帮助开发者更深入地理解网络编程。
一文了解Linux上TCP的几个内核参数调优
在Linux操作系统中,TCP的内核参数调优是一项关键任务,其中涉及的参数众多。针对内网环境,以下是几个主要的TCP参数及其调优建议:
1. **tcp_max_syn_backlog, somaxconn, tcp_abort_on_overflow**:这些参数控制内核TCP连接缓冲队列,防止因应用处理速度慢导致连接过多而溢出。应适当调大Backlog值,以避免连接在第三次握手后被意外丢弃,特别是衣柜源码对于NIO应用,以确保连接稳定性。
2. **tcp_syn_retries**:影响连接建立时的超时时间,建议设置为3次重传,以减少超时时间,对于Java,API提供了超时设置,但注意有些库可能未做此设置,可能导致不必要的延迟。
3. **tcp_retries2**:内核计算超时时间的重传次数,对于ReadTimeout较大的情况,降低tcp_retries2有助于快速从宕机机器恢复响应。
4. **tcp_slow_start_after_idle**:Linux默认开启这个参数来重置拥塞窗口,但对内网系统间调用影响不大,可能需要根据具体网络状况调整。
5. **初始CWND大小**:Linux初始CWND设置可能限制了大请求的传输效率,建议根据系统需求调整到更合适的值,如Linux 2.6.以上版本的K左右。
通过了解和调整这些参数,可以优化TCP连接性能,提高系统稳定性和响应速度。不过,每个场景的优化策略可能不同,务必结合实际环境进行调整。在学习过程中,可以加入交流群获取更多资源和支持。
详细讲解Linux内核角度分析tcpdump原理(1)
tcpdump是Linux系统抓包工具,基于libpcap库,能根据定义对网络数据包进行截获。它支持过滤网络层、协议、主机、网络或端口,并使用逻辑语句去除无用信息。tcpdump能分析网络行为,如丢包重传、报文详细信息和TCP分组。彩云源码通过保存捕获的数据包为pcap文件,使用wireshark打开,能更直观地分析问题。
tcpdump使用libpcap进行包捕获,使用bpf机制进行完美过滤。libpcap是Unix/Linux平台下的数据包捕获函数库,独立于系统用户层,提供链路层旁路处理。libpcap安装步骤包括库安装、测试、编译和错误处理。
在libpcap中,创建套接字使用AF_PACKET和SOCK_RAW,常用于抓包分析。socket函数调用__sock_create和packet_family_ops来创建socket,其中AF_PACKET模块对应创建函数packet_rcv,该函数用于接收链路层的包,然后根据应用层设置的过滤条件使用BPF进行过滤。
当网络包接收时,tcpdump创建PF_PACKET套接字,通过注册prot_hook完成准备工作。网络接收数据包时,会调用netif_receive_skb和__netif_receive_skb_core,其中后者会遍历ptype_all并执行deliver_skb函数,该函数调用packet_rcv进行过滤并添加到接收缓存。
当网络包发送时,Linux协议栈提供的报文发送函数会调用dev_queue_xmit或dev_hard_start_xmit,遍历ptype_all并执行deliver_skb和packet_rcv,将数据包发送给driver。最终,接收队列中的数据会copy给应用层,完成数据包的抓取。
文章总结了tcpdump从创建套接字到收发包的流程,以及使用libpcap和BPF进行过滤的过程。下篇文章将详细分析BPF过滤的实现。
如何测量和确定linux系统中tcp初始发送窗口的lpk源码大小?
如何测量和确定Linux系统中TCP初始发送窗口的大小?
答案涉及TCP协议的几个关键参数,包括rwnd(对端通告的窗口大小)和cwnd(本端的拥塞窗口)。在Linux实现中,发送窗口的初始大小由以下方式确定:wnd = min(rwnd, cwnd*mss)。其中mss是最大报文段大小。
了解初始发送窗口大小的一种方法是进行握手操作。新建一个连接,然后使用tcpdump抓取握手包,同时使用ss -it命令查看连接的cwnd字段以及wscale字段。通过抓取的握手包获取到的wnd字段,再用wnd乘以2的wscale次幂计算出rwnd。最终利用上述计算公式得到初始发送窗口大小。
另一种方法是直接查看Linux内核代码。寻找TCP_INIT_CWND宏定义,同样按照前述方法计算出rwnd。然后应用计算公式,得到初始发送窗口。
如果需要自定义初始cwnd和初始rwnd(在接收端进行修改),可以通过iproute2包中的ip route命令的cwnd、initcwnd、initrwnd参数进行调整。具体操作细节请参考ip route的官方文档。
通常情况下,除非对端接收设备老旧或运行的是非常老旧的操作系统,握手过程中对端反馈的初始rwnd通常大于cwnd*mss。因此,大多数情况下,初始cwnd已经接近于初始发送窗口的大小。
linux下安装tcpdump并用其抓包
在Linux环境中,为了深入探究网络协议,抓包分析数据是一种有效手段。尽管Windows用户可以轻松通过Wireshark进行抓包,但在Linux环境下,尤其在空间有限或不支持Wireshark的版本中,安装和使用tcpdump成为更好的选择。本文将简述如何在Linux下安装tcpdump并进行抓包操作。
首先,有两种安装tcpdump的方法。一是从源代码编译安装,可通过参考csdn博客(blog.csdn.net/tic_yx/article/details/...)获取详细的步骤。另一种更为便捷,就是在Ubuntu等系统中,通过命令行输入`sudo apt-get install tcpdump`,如果遇到安装问题,可以尝试更换国内的软件源,如清华大学源。
在使用tcpdump时,常用命令包括实时查看抓包信息,将捕获的数据保存为pcap文件以便后续分析,以及通过过滤指定端口号并保存至文件。这样,即使在Linux上完成抓包,也可以方便地将文件传输到Windows系统,利用Wireshark进行深入分析。
总的来说,Wireshark提供了强大的抓包和分析功能,但在Linux环境中不便安装时,使用tcpdump进行抓包并导出至Windows进行后续处理,不失为一个实用且灵活的解决方案。
ç è°linuxä¸TCPï¼ä¸ï¼
tcp åè®® æ¯äºèç½ä¸æ常ç¨çåè®® ï¼ å¼å人ååºæ¬ä¸å¤©å¤©åå®æ交éï¼å¯¹å®è¿è¡æ·±å ¥äºè§£ã å¯ä»¥å¸®å©æ们ææ¥å®ä½bugåè¿è¡ç¨åºä¼åãä¸é¢æå°å°±TCPå 个ç¹åæ·±å ¥çæ¢è®¨å®¢æ·ç«¯ï¼æ¶å° ack å åé è¿æ¥èµæºã åéæ°æ®
æå¡å¨ : æ¶å° syn åç«å³ åé è¿æ¥èµæº
客æ·ç«¯ï¼æ¶å°ACKï¼ ç«å³åé èµæº
æå¡å¨ï¼æ¶å°ACKï¼ ç«å³åé èµæº
æ¢ç¶ä¸æ¬¡æ¡æä¹ä¸æ¯%å¯é ï¼ é£å次ï¼äºæ¬¡ï¼å 次ãããå¢? å ¶å®é½ä¸æ ·ï¼ä¸ç®¡å¤å°æ¬¡é½æ丢å é®é¢ã
client åªåéä¸ä¸ª SYNï¼ server åé ä¸ä¸ªtcbï¼ æ¾å ¥synéåä¸ã è¿æ¶åè¿æ¥å«åè¿æ¥ç¶æï¼å¦æserver æ¶ä¸å° client çACKï¼ ä¼ä¸åéè¯ åé ACK-SYN ç»client ãéè¯é´é 为 2 ç N æ¬¡æ¹ å å ï¼2^0 , 2^1, 2^2 ....ï¼ï¼ç´è³è¶ æ¶æéæ¾synéåä¸çè¿ä¸ª TCB;
å¨åè¿æ¥ç¶æä¸ï¼ ä¸æ¹é¢ä¼å ç¨éåé é¢èµæºï¼å¦ä¸æ¹é¢å ç¨å åèµæºãæ们åºè¯¥è®©åè¿æ¥ç¶æåå¨æ¶é´å°½å¯è½çå°
å½client åä¸ä¸ªæªæå¼ç端å£åèµ·è¿æ¥è¯·æ±æ¶ï¼ä¼æ¶å°ä¸ä¸ªRSTåå¤å
å½listen ç backlog å somaxconn é½è®¾ç½®äºå¾æ¶åï¼ å两è minå¼
Recv-Q æ¯accept éåå½å个æ°ï¼ Send-Q 设置æ大å¼
è¿ç§SYN洪水æ»å»æ¯ä¸ç§å¸¸è§æ»å»æ¹å¼ï¼å°±æ¯å©ç¨åè¿æ¥éåç¹æ§ï¼å 满syn éåç èµæºï¼å¯¼è´ clientæ æ³è¿æ¥ä¸ã
解å³æ¹æ¡:
为ä»ä¹ä¸åæ¡æé£æ ·å并æä¸æ¬¡æ¥æ? å 为ååå¼å§è¿æ¥æ åµï¼è¿æ¥æ¯å¤§å®¶é½ä»0å¼å§ï¼ å ³éæ¶æåå²å 袱çãserver(被å¨å ³éæ¹) æ¶å° client(主å¨å ³éæ¹) çå ³é请æ±FINå ã è¿æ¶åå¯è½è¿ææªåéå®çæ°æ®ï¼ä¸è½ä¸¢å¼ã æ以éè¦åå¼ãäºå®å¯è½æ¯è¿æ ·
å½ç¶ï¼å¨æ²¡æå¾ åæ°æ®ï¼å¹¶ä¸å 许 Delay ACK æ åµä¸ï¼ FIN-ACKå并è¿æ¯é常常è§çäºæ ï¼è¿æ¯ä¸æ¬¡æ¥ææ¯å¯ä»¥çã
åä¸
CLOSE_WAIT æ¯è¢«å¨å ³éæ¹ææçç¶æã
被å¨å ³éæ¹ [æ¶å° FIN å åé ACK åºç] å° [åéFINï¼ æ¶å°ACK ] æé´çç¶æ为 CLOSE_WAITï¼ è¿ä¸ªç¶æä»ç¶è½åéæ°æ®ã æ们å«ååå ³é, ä¸é¢ç¨ä¸ªä¾åæ¥åæ:
è¿ä¸ªæ¯æå®é ç产ç¯å¢ç¢°å°çä¸ä¸ªé®é¢ï¼é¿è¿æ¥ä¼è¯åºæ¯ï¼server端æ¶å°clientçrpc call 请æ±1ï¼å¤çåç°è¯·æ±å æé®é¢ï¼å°±å¼ºå¶å ³éç»æè¿æ¬¡ä¼è¯ï¼ ä½æ¯ å 为client åé 第äºæ¬¡è¯·æ±ä¹åï¼å¹¶æ²¡æå»è°ç¨recvï¼æ以并ä¸ç¥é è¿ä¸ªè¿æ¥è¢«serverå ³éï¼ ç»§ç»åé 请æ±2 ï¼ æ¤æ¶æ¯åè¿æ¥ï¼è½å¤æååéå°å¯¹ç«¯æºå¨ï¼ä½æ¯recvç»æåï¼éå°è¿æ¥å·²ç»å ³éé误ã
å¦æ client å server æ°å¥½åæ¶åèµ·å ³éè¿æ¥ãè¿ç§æ åµä¸ï¼ä¸¤è¾¹é½æ¯ä¸»å¨è¿æ¥ï¼é½ä¼è¿å ¥ TIME_WAITç¶æ
1ã被å¨å ³éæ¹å¨LAST_ACKç¶æ(å·²ç»åéFIN)ï¼çå¾ ä¸»å¨å ³éæ¹çACKåºçï¼ä½æ¯ ACK丢æï¼ ä¸»å¨æ¹å¹¶ä¸ç¥éï¼ä»¥ä¸ºæåå ³éãå 为没æTIME_WAITçå¾ æ¶é´ï¼å¯ä»¥ç«å³å建æ°çè¿æ¥ï¼ æ°çè¿æ¥åéSYNå°åé¢é£ä¸ªæªå ³éç被å¨æ¹ï¼è¢«å¨æ¹è®¤ä¸ºæ¯æ¶å°é误æ令ï¼ä¼åéRSTã导è´å建è¿æ¥å¤±è´¥ã
2ã主å¨å ³éæ¹æå¼è¿æ¥ï¼å¦æ没æTIME_WAITçå¾ æ¶é´ï¼å¯ä»¥é©¬ä¸å»ºç«ä¸ä¸ªæ°çè¿æ¥ï¼ä½æ¯åä¸ä¸ªå·²ç»æå¼è¿æ¥çï¼å»¶è¿å°è¾¾çæ°æ®å ã 被æ°å»ºçè¿æ¥æ¥æ¶ï¼å¦æå好seq å ackå段 é½æ£ç¡®, seqå¨æ»å¨çªå£èå´å (åªè½è¯´æºçé常å°ï¼ä½æ¯è¿æ¯æå¯è½ä¼åç)ï¼ä¼è¢«å½ææ£ç¡®æ°æ®å æ¥æ¶ï¼å¯¼è´æ°æ®ä¸²å ã å¦æä¸å¨windowèå´å ï¼å没æå½±å( åéä¸ä¸ªç¡®è®¤æ¥æï¼ack å段为ææackçåºåå·ï¼seq为å½ååéåºåå·ï¼ï¼ç¶æåä¿æåæ ·)
TIME_WAIT é®é¢æ¯è¾æ¯è¾å¸¸è§ï¼ç¹å«æ¯CGIæºå¨ï¼å¹¶åéé«ï¼å¤§éè¿æ¥å段æå¡çtcpçè¿æ¥ãå æ¤ä¹è¡çåºäºå¤ç§æ段解å³ãè½ç¶æ¯ç§æ¹æ³è§£å³ä¸æ¯é£ä¹å®ç¾ï¼ä½æ¯å¸¦æ¥ç好å¤ä¸è¬å¤äºåå¤ãè¿æ¯å¨æ¥å¸¸å·¥ä½ä¸ä¼ä½¿ç¨ã
1ãæ¹çTIME_WAIT çå¾ æ¶é´
è¿ä¸ªæ¯ç¬¬ä¸ä¸ªæ³å°ç解å³åæ³ï¼æ¢ç¶çå¾ æ¶é´å¤ªé¿ï¼å°±æ¹ææ¶é´çï¼å¿«éåæ¶ç«¯å£ãä½æ¯å®é æ åµå¾å¾ä¸ä¹è§ï¼å¯¹äºå¹¶åçæºå¨ï¼ä½ æ¹å¤çæè½ä¿è¯åæ¶é度å¢ï¼ææ¶åå ç§éå°±å ä¸ä¸ªè¿æ¥ã太ççè¯ï¼å°±ä¼æåé¢ä¸¤ç§é®é¢å°æ¦çåçã
2ãç¦æ¢Socket lingering
è¿ç§æ åµä¸å ³éè¿æ¥ï¼ä¼ç´æ¥æå¼ç¼å²åºä¸å¾ åéçæ°æ®ï¼ä¼åéä¸ä¸ªRSTç»å¯¹ç«¯ï¼ç¸å½äºç´æ¥æå¼TIME_WAITï¼ è¿å ¥CLOSEç¶æãåæ ·å 为åæ¶äº TIME_WAIT ç¶æï¼ä¼æåé¢ä¸¤ç§é®é¢å°æ¦çåçã
3ãtcp_tw_reuse
net.ipv4.tcp_tw_reuseéé¡¹æ¯ ä» TIME_WAIT ç¶æçéåä¸ï¼éåæ¡ä»¶ï¼1ãremote ç ip å端å£ç¸åï¼ 2ãéåä¸ä¸ªæ¶é´æ³å°äºå½åæ¶é´æ³ï¼ ç¨æ¥è§£å³ç«¯å£ä¸è¶³çå°´å°¬ã
ç°å¨ç«¯å£å¯ä»¥å¤ç¨äºï¼ççå¦ä½é¢å¯¹åé¢TIME_WAIT é£ä¸¤ç§é®é¢ã æ们ä»ç»å顾ç¨ä¸ä¸åé¢ä¸¤ç§é®é¢ãé½æ¯å¨æ°å»ºè¿æ¥ä¸æ¶å°èè¿æ¥çå 导è´çé®é¢ï¼ é£ä¹å¦ææè½å¨æ°è¿æ¥ä¸è¯å«åºæ¤å 为éæ³å ï¼æ¯ä¸æ¯å°±å¯ä»¥ä¸¢æè¿äºæ ç¨å ï¼è§£å³é®é¢å¢ã
éè¦å®ç°è¿äºåè½ï¼éè¦æ©å±ä¸ä¸tcp å 头ã å¢å æ¶é´æ³å段ã åéè å¨æ¯æ¬¡åéçæ¶åã å¨tcpå 头éé¢å¸¦ä¸åéæ¶åçæ¶é´æ³ã å½æ¥æ¶è æ¥æ¶çæ¶åï¼å¨ACKåºçä¸é¤äºTCPå 头ä¸å¸¦èªå·±æ¤æ¶åéçæ¶é´æ³ï¼å¹¶ä¸ææ¶å°çæ¶é´æ³éå å¨åé¢ãä¹å°±æ¯è¯´ACKå ä¸æ两个æ¶é´æ³å段ãç»æå¦ä¸:
é£æ们æ¥ä¸æ¥ä¸ä¸ªä¸ªåætcp_tw_reuseæ¯å¦ä½è§£å³TIME_WAITç两个é®é¢ç
4ãtcp_tw_recycle
tcp_tw_recycle ä¹æ¯åå© timestampæºå¶ã顾åæä¹ï¼ tcp_tw_reuse æ¯å¤ç¨ 端å£ï¼å¹¶ä¸ä¼åå° TIME-WAIT æ°éãä½ å»æ¥è¯¢æºå¨ä¸TIME-WAIT æ°éï¼è¿æ¯ å åå ä¸ä¸ªï¼è¿ç¹å¯¹æ强迫ççåå¦æè§å¾ä¸èæãtcp_tw_recycle æ¯ æå åæ¶ TIME-WAITèµæºãä¼åå° æºå¨ä¸ TIME-WAIT æ°éã
tcp_tw_recycle å·¥ä½åçæ¯ã
一文从linux源码看socket的close基本概括
理解TCP关闭过程的关键在于四次挥手,这个过程是主动关闭、被动关闭和同时关闭的统一体现。在主动关闭close(fd)的过程中,通过C语言中的close(int fd)函数调用系统调用sys_close,进而执行filp_close方法。随后,fput函数处理多进程中的socket引用问题,确保父进程也正确关闭socket。在f_op->release的实现中,我们关注socket与file的关系以及close(fd)调用链。随着状态机的变迁,TCP从FIN_WAIT1变迁至FIN_WAIT2,设置一个TCP_FIN_WAIT2定时器,防止由于对端未回应导致的长时间等待。FIN_WAIT2状态等待对端的FIN,完成最后两次挥手。接收对端FIN后,状态变化至time_wait,原socket资源被回收,并在时间等待超时后从系统中清除。在被动关闭中,接收FIN进入close_wait状态,应用关闭连接时改变状态为last_ack,并发送本端的FIN。被动关闭的后两次挥手后,连接关闭。出现大量close_wait通常与应用检测到对端FIN时未及时关闭有关,解决方法包括调整连接池的参数或加入心跳检测。操作系统通过包活定时器在超时后强制关闭连接。进程退出时会关闭所有文件描述符,再次触发filp_close函数。在Java中,通过重写finalize方法,GC会在释放内存时关闭未被引用的socket,但不可完全依赖GC来管理socket资源,以避免潜在的内存泄露问题。总结,深入理解TCP关闭过程有助于优化网络应用程序的性能和稳定性,同时阅读Linux内核源代码需要耐心和系统性的方法。
从 Linux源码 看 Socket(TCP)的accept
从 Linux 源码角度探究 Server 端 Socket 的 Accept 过程(基于 Linux 3. 内核),以下是一系列关键步骤的解析。
创建 Server 端 Socket 需依次执行 socket、bind、listen 和 accept 四个步骤。其中,socket 系统调用创建了一个 SOCK_STREAM 类型的 TCP Socket,其操作函数为 TCP Socket 所对应的 ops。在进行 Accept 时,关键在于理解 Accept 的功能,即创建一个新的 Socket 与对端的 connect Socket 进行连接。
在具体实现中,核心函数 sock->ops->accept 被调用。关注 TCP 实现即 inet_stream_ops->accept,其进一步调用 inet_accept。核心逻辑在于 inet_csk_wait_for_connect,用于管理 Accept 的超时逻辑,避免在超时时惊群现象的发生。
EPOLL 的实现中,"惊群"现象是由水平触发模式下 epoll_wait 重新塞回 ready_list 并唤醒多个等待进程导致的。虽然 epoll_wait 自身在有中断事件触发时不惊群,但水平触发机制仍会造成类似惊群的效应。解决此问题,通常采用单线程专门处理 accept,如 Reactor 模式。
针对"惊群"问题,Linux 提供了 so_reuseport 参数,允许多个 fd 监听同一端口号,内核中进行负载均衡(Sharding),将 accept 任务分散到不同 Socket 上。这样,可以有效利用多核能力,提升 Socket 分发能力,且线程模型可改为多线程 accept。
在 accept 过程中,accept_queue 是关键成员,用于填充添加待处理的连接。用户线程通过 accept 系统调用从队列中获取对应的 fd。值得注意的是,当用户线程未能及时处理时,内核可能会丢弃三次握手成功的连接,导致某些意外现象。
综上所述,理解 Linux Socket 的 Accept 过程需要深入源码,关注核心函数与机制,以便优化 Server 端性能,并有效解决"惊群"等问题,提升系统处理能力。
linux如何实现tcp/ip协议?
在深入探讨 Linux 中 TCP/IP 协议的实现时,我们不仅需要理解基本的三次握手过程,还需洞悉内核底层的复杂操作。三次握手不仅涉及状态流转,还包括端口选择、半连接队列、syncookie、全连接队列、重传计时器等关键操作。这些深入了解将显著提升你对线上问题的把握与理解能力,在面试中无疑能为你加分。 三次握手的主要流程如下:服务器通过创建 socket、绑定端口、listen 监听并接受客户端请求。
客户端创建 socket,调用 connect 连接服务器。
这看似简单的几个系统调用,背后却蕴含着内核底层的复杂操作。以下是对三次握手过程的内部操作详细解析:一、服务器的 listen
服务器在提供服务前会 listen,此时内核会计算半连接队列长度,据此申请内存用于管理半连接队列对象,同时将队列挂到接收队列上。全连接队列作为链表形式初始化,等待连接请求。二、客户端 connect
客户端发起 connect 请求时,将状态设置为 TCP_SYN_SENT,通过动态选择端口,构造并发送 SYN 握手包,同时启动重传定时器。三、服务器响应 SYN
服务器响应 SYN 包,检查全/半连接队列,构造 SYNACK 并发送,同时将握手信息添加到半连接队列,开启重传定时器。四、客户端响应 SYNACK
客户端收到 SYNACK 后,修改状态为 ESTABLISHED,清除重传定时器,开启保活计时器,并发送第三次握手的 ACK。五、服务器响应 ACK
服务器响应 ACK,检查全连接队列,若未满则创建新 socket,添加到全连接队列,设置连接状态为 ESTABLISHED。六、服务器 accept
accept 操作从全连接队列取出连接请求,返回给用户进程。 通过以上解析,你能够更深入地理解三次握手的过程,对于线上问题排查具有极大帮助。同时,内核中的握手过程还涉及丢包重传、计时器控制等细节,对这些问题的了解也有助于优化网络性能。深入理解这些内部机制,将使你具备处理复杂网络问题的能力。