UNIX网络编程——SOCKET API和TCP STATE的对应关系_三次握手_四次挥手及TCP延迟确认
在socket系统调用中,如何完成三次握手和四次挥手:
SOCK_DGRAM即UDP中的connect操作知识在内核中注册对方机器的IP和PORT信息,并没有建立连接的过程,即没有发包,close也不发包)。
而SOCK_STREAM对应如下:
connect会完成TCP的三次握手,客户端调用connect后,由内核中的TCP协议完成TCP的三次握手;
close操作会完成四次挥手。
三次握手对应的Berkeley Socket API:
可以看出和连接建立相关的API有:connect, listen,accept 3个,connect用在客户端,另外2个用在服务端。
对于TCP/IP protocol stack来说,TCP层的tcp_in&tcp_out也参与这个过程。我们这里只讨论这3个应用层的API干了什么事情。
(1) connect
发送了一个SYN,收到Server的SYN+ACK后,代表连接完成。发送最后一个ACK是protocol stack,tcp_out完成的。
(2)listen
在server这端,准备了一个未完成的连接队列,保存只收到SYN_C的socket结构;
还准备了已完成的连接队列,即保存了收到了最后一个ACK的socket结构。
(3)accept
应用进程调用accept的时候,就是去检查上面说的已完成的连接队列,如果已完成的队列里有连接,就返回这个连接;如果没有,即空的,blocking方试调用,就睡眠等待;nonblocking方式调用,就直接返回,一般一"EWOULDBLOCK“ errno告诉调用者,连接队列是空的。
注意:
在上面的socket API和TCP STATE的对应关系中,TCP协议中,客户端收到Server响应时,可能会有会延迟确认。
即客户端收到数据后,会阻塞给Server端确认。
可以在每次收到数据后:
调用setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){1}, sizeof(int)); 快速给Server端确认。
我们如何判断有一个建立连接请求或一个关闭连接请求:
建立连接请求:
1、connect将完成三次握手,accept所监听的fd上,产生读事件,表示有新的连接请求;
关闭连接请求:
1、close将完成四次挥手,如果有一方关闭sockfd,对方将感知到有读事件,
如果read读取数据时,返回0,即读取到0个数据,表示有断开连接请求。(在操作系统中已经这么定义)
关闭连接过程中的TCP状态和SOCKET处理,及可能出现的问题:
TIME_WAIT
TIME_WAIT 是主动关闭 TCP 连接的那一方出现的状态,系统会在 TIME_WAIT 状态下等待 2MSL(maximum segment lifetime )后才能释放连接(端口)。通常约合 4 分钟以内。
进入 TIME_WAIT 状态等待 2MSL 的目的:
1、确保连接可靠地关闭; 即防止最后一个ACK丢失。
2、避免产生套接字混淆(同一个端口对应多个套接字)。
意思是,一方close发送了关闭连接请求,对方的应答迟迟到不了(例如网络原因),导致TIME_WAIT超时,此时这个端口又可用了,我们在这个端口上又建立了另外一个socket连接。如果此时对方的应答到了,怎么处理呢?其实这个在TCP层已经处理了,由于有TCP序列号,所以内核TCP层,就会将包丢掉,并给对方发包,让对方将sockfd关闭。 所以应用层是没有关系的。即我们用socket API编写程序,就不用处理。
注意:
TIME_WAIT是指操作系统的定时器会等2MSL,而主动关闭sockfd的一方,并不会阻塞。(即应用程序在close时,并不会阻塞)。
当主动方关闭sockfd后,对方可能不知道这个事件。那么当对方(被动方)写数据,即send时,将会产生错误,即errno为: ECONNRESET。
服务器产生大量 TIME_WAIT 的原因:(一般我们不这样开发Server)
服务器存在大量的主动关闭操作,需关注程序何时会执行主动关闭(如批量清理长期空闲的套接字等操作)。
一般我们自己写的服务器进行主动断开连接的不多,除非做了空闲超时之类的管理。(TCP短连接是指,客户端发送请求给服务器,客户端收到服务器端的响应后,关闭连接)。
CLOSE_WAIT
CLOSE_WAIT 是被动关闭 TCP 连接时产生的,如果收到另一端关闭连接的请求后,本地(Server端)不关闭相应套接字就会导致本地套接字进入这一状态。
(如果对方关闭了,没有收到关闭连接请求,就是下面的不正常情况)
按状态机,我方收到FIN,则由TCP实现发送ACK,因此进入CLOSE_WAIT状态。但如果我方不执行close(),就不能由CLOSE_WAIT迁移到LAST_ACK,则系统中会存在很多CLOSE_WAIT状态的连接。
如果存在大量的 CLOSE_WAIT,则说明客户端并发量大,且服务器未能正常感知客户端的退出,也并未及时 close 这些套接字。(如果不及时处理,将会出现没有可用的socket描述符的问题,产生问题的原因,没有及时close)。
正常情况下,一方关闭sockfd,另外一方将会有读事件产生, 当recv数据时,如果返回值为0,表示对端已经关闭。此时我们应该调用close,将对应的sockfd也关闭掉。
不正常情况下,一方关闭sockfd,另外一方并不知道,(比如在close时,自己断网了,对方就收不到发送的数据包)。此时,如果另外一方再向对应的sockfd上写send或读recv数据。
recv时,将会返回0,表示连接已经断开。
send时, 将会产生错误,errno为ECONNRESET。
UNIX网络编程——SOCKET API和TCP STATE的对应关系_三次握手_四次挥手及TCP延迟确认的更多相关文章
- TCP/IP协议全解析 三次握手与四次挥手[转]
所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立.所谓四次挥手(Four-Way Wavehand) ...
- TCP常见的定时器及三次握手与四次挥手
1.TCP常见的定时器 在TCP协议中有的时候需要定期或者按照某个算法对某个事件进行触发,那么这个时候,TCP协议是使用定时器进行实现的.在TCP中,会有七种定时器: 建立连接定时器(connecti ...
- TCP 的三次握手和四次挥手,TCP 的流量控制和拥塞控制
70.TCP协议的三次握手与四次挥手70.1.TCP报文结构 1.源端口号:表示发送端端口号,字段长为16位. 2.目标端口号:表示接收端口号,字段长为16位. 3.序列号:表示发送数据的位置 ...
- 使用 tcpdump 抓包分析 TCP 三次握手、四次挥手与 TCP 状态转移
目录 文章目录 目录 前文列表 TCP 协议 图示三次握手与四次挥手 抓包结果 抓包分析 TCP 三次握手 数据传输 四次挥手 TCP 端口状态转移 状态转移 前文列表 <常用 tcpdump ...
- tcp建立连接为什么需要三次握手和四次挥手
前言 众所周知tcp传输层协议在建立连接的时候需要三次才能建立起一个真正的可靠连接,可是为什么是三次呢,不可以是两次,四次等等呢,可以自己思考一番,带着疑问可以看下文. 三次握手 在<计算机网络 ...
- 三次握手和四次挥手以及TCP标志位的详细介绍
一.TCP标志位 在讲TCP三次握手和四次挥手之前,先说一下TCP标志位,方便后续的理解. 简单来说,TCP标志位的值代表了当前请求的目的. 标志位一共有6种,分别是: SYN(synchronous ...
- 用wireshark抓包分析TCP三次握手、四次挥手以及TCP实现可靠传输的机制
关于TCP三次握手和四次挥手大家都在<计算机网络>课程里学过,还记得当时高超老师耐心地讲解.大学里我遇到的最好的老师大概就是这位了,虽然他只给我讲过<java程序设计>和< ...
- TCP连接的建立(三次握手和四次挥手)
写到最后发现我描述的挺水的,这个老哥的用语比较专业一点https://blog.csdn.net/qq_38950316/article/details/81087809 (老哥这篇有些许错别字 大 ...
- tcp连接过程中的三次握手和四次挥手
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手握手建立连接 @第一次握手: 建立连接是,客户端A发送SYN包到服务器B,并进入SYN_SEND状态,等待B确认. @第二次握手: 服务 ...
随机推荐
- hdu 5592 BestCoder Round #65(树状数组)
题意: ZYB有一个排列PP,但他只记得PP中每个前缀区间的逆序对数,现在他要求你还原这个排列. (i,j)(i < j)(i,j)(i<j)被称为一对逆序对当且仅当A_i>A_jA ...
- Codeforces #Round 406(Div.2)
来自FallDream的博客,未经允许,请勿转载,谢谢. ------------------------------------------------------- 大家好,我是一个假人.在学习O ...
- C#+HtmlAgilityPack+Dapper走一波爬虫
最近因为公司业务需要,又有机会撸winform了,这次的需求是因为公司有项目申报的这块业务,项目申报前期需要关注政府发布的相关动态信息,政府部门网站过多,人工需要一个一个网站去浏览和查阅,有时候还会遗 ...
- 聊聊并发(一)深入分析Volatile的实现原理
本文属于作者原创,原文发表于InfoQ:http://www.infoq.com/cn/articles/ftf-java-volatile 引言 在多线程并发编程中synchronized和Vola ...
- spark学习笔记01
spark学习笔记01 1.课程目标 1.熟悉spark相关概念 2.搭建一个spark集群 3.编写简单spark应用程序 2.spark概述 spark是什么 是基于内存的分布式计算引擎,计算速度 ...
- [HCNA]VLAN配置Hybrid接口
实验名称 VLAN配置Hybrid接口 日期 2018年4月13日 实验目的 1.掌握配置Hybrid接口的方法. 2.理解Hybrid接口处理Untagged数据帧过程 3.理解Hybrid接口处理 ...
- jmeter分布式测试远程连接失败
jmeter分布式部署其实很简单.但今天测试的时候发现了一个坑,远程连接一直失败. 原因:服务器上部署了slave,而这台服务器上有多个网卡.举个例子:ip分别为:192.168.100.6,10.1 ...
- 动手实现一个vue中的模态对话框组件
写在前面 对话框是很常用的组件 , 在很多地方都会用到,一般我们可以使用自带的alert来弹出对话框,但是假如是设计 出的图该怎么办呢 ,所以我们需要自己写一个对话框,并且如果有很多地方都用到,那我们 ...
- Java中next()和nextLine()
next()读取到有效字符后才可以结束输入,对输入有效字符之前遇到的空格键.Tab键或Enter键等结束符,next()方法会自动将其去掉,只有在输入有效字符之后,next()方法才将其后输入的空格键 ...
- 终止Docker容器
可以使用 docker stop 来终止一个运行中的容器. 此外,当Docker容器中指定的应用终结时,容器也自动终止. 例如对于上一章节中只启动了一个终端的容器,用户通过 exit 命令或 Ctrl ...