TCP关闭连接的两种方式

简介: 【4月更文挑战第5天】close 和 shutdown 的函数

一个 TCP 连接需要经过三次握手进入数据传输阶段,最后来到连接关闭阶段。在最后的连接关闭阶段,我们需要重点关注的是“半连接”状态。

客户端到服务器端的方向,指的是客户端通过套接字接口,向服务器端发送 TCP 报文;而服务器端到客户端方向则是另一个传输方向。在绝大多数情况下,TCP 连接都是先关闭一个方向,此时另外一个方向还是可以正常进行数据传输。


close 函数

最常见的 close 函数:

int close(int sockfd)

这个函数很简单,对已连接的套接字执行 close 操作就可以,若成功则为 0,若出错则为 -1。


这个函数会对套接字引用计数减一,一旦发现套接字引用计数到 0,就会对套接字进行彻底释放,并且会关闭 TCP 两个方向的数据流。


套接字引用计数是什么意思呢?因为套接字可以被多个进程共享,你可以理解为我们给每个套接字都设置了一个积分,如果我们通过 fork 的方式产生子进程,套接字就会积分 +1, 如果我们调用一次 close 函数,套接字积分就会 -1。这就是套接字引用计数的含义。


close 函数具体是如何关闭两个方向的数据流呢?


在输入方向,系统内核会将该套接字设置为不可读,任何读操作都会返回异常。


在输出方向,系统内核尝试将发送缓冲区的数据发送给对端,并最后向对端发送一个 FIN 报文,接下来如果再对该套接字进行写操作会返回异常。


如果对端没有检测到套接字已关闭,还继续发送报文,就会收到一个 RST 报文,告诉对端:“Hi, 我已经关闭了,别再给我发数据了。”


close 函数并不能帮助我们关闭连接的一个方向,那么如何在需要的时候关闭一个方向呢?幸运的是,设计 TCP 协议的人帮我们想好了解决方案,这就是 shutdown 函数。


shutdown 函数

shutdown 函数的原型是这样的:

int shutdown(int sockfd, int howto)

对已连接的套接字执行 shutdown 操作,若成功则为 0,若出错则为 -1。


howto 是这个函数的设置选项,它的设置有三个主要选项:

  • SHUT_RD(0):关闭连接的“读”这个方向,对该套接字进行读操作直接返回 EOF。从数据角度来看,套接字上接收缓冲区已有的数据将被丢弃,如果再有新的数据流到达,会对数据进行 ACK,然后悄悄地丢弃。也就是说,对端还是会接收到 ACK,在这种情况下根本不知道数据已经被丢弃了。
  • SHUT_WR(1):关闭连接的“写”这个方向,这就是常被称为“半关闭”的连接。此时,不管套接字引用计数的值是多少,都会直接关闭连接的写方向。套接字上发送缓冲区已有的数据将被立即发送出去,并发送一个 FIN 报文给对端。应用程序如果对该套接字进行写操作会报错。
  • SHUT_RDWR(2):相当于 SHUT_RD 和 SHUT_WR 操作各一次,关闭套接字的读和写两个方向。


close 和 shutdown 的差别

第一个差别:close 会关闭连接,并释放所有连接对应的资源,而 shutdown 并不会释放掉套接字和所有的资源。


第二个差别:close 存在引用计数的概念,并不一定导致该套接字不可用;shutdown 则不管引用计数,直接使得该套接字不可用,如果有别的进程企图使用该套接字,将会受到影响。


第三个差别:close 的引用计数导致不一定会发出 FIN 结束报文,而 shutdown 则总是会发出 FIN 结束报文,这在我们打算关闭连接通知对端的时候,是非常重要的。

image.png

使用 close 函数关闭连接有两个需要明确的地方。

  • close 函数只是把套接字引用计数减 1,未必会立即关闭连接;
  • close 函数如果在套接字引用计数达到 0 时,立即终止读和写两个方向的数据传送。


基于这两点,在期望关闭连接其中一个方向时,应该使用 shutdown 函数。

相关文章
|
缓存
银河麒麟server-V10配置镜像源
银河麒麟server-V10配置镜像源
16313 1
|
2月前
|
人工智能 监控 并行计算
厨房食品卫生与安全检测14类数据集(18万张图片,已划分、已标注)——AI智能检测的行业实践基石
本数据集包含18万张标注图像,覆盖蟑螂、老鼠、口罩佩戴等14类厨房安全目标,专为YOLO等目标检测模型设计,助力AI实现厨房卫生智能监控,推动食品安全数字化升级。
厨房食品卫生与安全检测14类数据集(18万张图片,已划分、已标注)——AI智能检测的行业实践基石
|
缓存 Linux 开发工具
CentOS 7- 配置阿里镜像源
阿里镜像官方地址http://mirrors.aliyun.com/ 1、点击官方提供的相应系统的帮助 :2、查看不同版本的系统操作: 下载源1、安装wget yum install -y wget2、下载CentOS 7的repo文件wget -O /etc/yum.
261620 0
|
5月前
|
人工智能 测试技术 API
2025 API 开发工具深度分析:Apifox 与 Apipost
2025年,AI功能对于API开发工具选择至关重要。本文深入对比国产主流工具Apifox与Apipost,从AI能力、协议支持、Mock服务、文档管理、团队协作等方面全面分析。Apipost在AI智能化、WebSocket支持、智能Mock生成及团队协作上优势明显,适合中大型团队与复杂业务场景;Apifox则适合轻量级调试需求的个人或小型项目。根据实际需求选型,助你提升开发效率。
318 6
|
10月前
|
NoSQL Java 中间件
【📕分布式锁通关指南 02】基于Redis实现的分布式锁
本文介绍了从单机锁到分布式锁的演变,重点探讨了使用Redis实现分布式锁的方法。分布式锁用于控制分布式系统中多个实例对共享资源的同步访问,需满足互斥性、可重入性、锁超时防死锁和锁释放正确防误删等特性。文章通过具体示例展示了如何利用Redis的`setnx`命令实现加锁,并分析了简化版分布式锁存在的问题,如锁超时和误删。为了解决这些问题,文中提出了设置锁过期时间和在解锁前验证持有锁的线程身份的优化方案。最后指出,尽管当前设计已解决部分问题,但仍存在进一步优化的空间,将在后续章节继续探讨。
1262 131
【📕分布式锁通关指南 02】基于Redis实现的分布式锁
|
5月前
|
数据采集 边缘计算 定位技术
ar景区导航导览开发方案:核心技术架构与功能设计
本方案针对传统景区导航吸引力弱、互动性差等问题,融合三维建模、多源定位与AR引擎技术,实现室内外精准导航与AR互动体验。支持AR寻宝等功能,提升游客体验与景区竞争力。
364 0
|
机器学习/深度学习 前端开发 JavaScript
WebAssembly:让前端性能突破极限的秘密武器
WebAssembly(简称 WASM)作为前端开发的性能加速器,能够让代码像 C++ 一样在浏览器中高速运行,突破了 JavaScript 的性能瓶颈。本文详细介绍了 WebAssembly 的概念、工作原理以及其在前端性能提升中的关键作用。通过与 JavaScript 的配合,WASM 让复杂运算如图像处理、3D 渲染、机器学习等在浏览器中流畅运行。文章还探讨了如何逐步集成 WASM,展示其在网页游戏、高计算任务中的实际应用。WebAssembly 为前端开发者提供了新的可能性,是提升网页性能、优化用户体验的关键工具。
5890 2
WebAssembly:让前端性能突破极限的秘密武器
|
12月前
|
索引 搜索推荐 UED
基于elasticsearch + huggingface model 实现语义检索
项目地址:https://github.com/skyterra/elastic-embedding-searcher。本项目利用Hugging Face模型生成文本的嵌入向量,并将其同步至Elasticsearch创建索引,支持通过余弦相似度进行高效的向量搜索,实现精准的内容检索与推荐功能。该项目为开发智能搜索应用提供了强大的后端支持。 (该简介有239个字符,包括标点和空格)
381 8
|
12月前
|
运维 jenkins Java
Jenkins 自动化局域网管控软件构建与部署流程
在企业局域网管理中,Jenkins 作为自动化工具,通过配置源码管理、构建及部署步骤,实现了高效、稳定的软件开发与部署流程,显著提升局域网管控软件的开发与运维效率。
229 5
|
网络协议 算法 Linux
TCP教程:详解TCP连接过程
TCP教程:详解TCP连接过程
1677 0