close 和 shutdown 的差别
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 操作各一次,关闭套接字的读和写两个方向。
讲到这里,不知道你是不是有和我当初一样的困惑,使用 SHUT_RDWR 来调用 shutdown 不是和 close 基本一样吗,都是关闭连接的读和写两个方向。
第一个差别:close 会关闭连接,并释放所有连接对应的资源,而 shutdown 并不会释放掉套接字和所有的资源。
第二个差别:close 存在引用计数的概念,并不一定导致该套接字不可用;shutdown 则不管引用计数,直接使得该套接字不可用,如果有别的进程企图使用该套接字,将会受到影响。
第三个差别:close 的引用计数导致不一定会发出 FIN 结束报文,而 shutdown 则总是会发出 FIN 结束报文,这在我们打算关闭连接通知对端的时候,是非常重要的。
总结
我们讲述了 close 函数关闭连接的方法,
使用 close 函数关闭连接有两个需要明确的地方。close 函数只是把套接字引用计数减 1,未必会立即关闭连接;
close 函数如果在套接字引用计数达到 0 时,立即终止读和写两个方向的数据传送。基于这两个确定,在期望关闭连接其中一个方向时,应该使用 shutdown 函数。
在大多数情况下,我们会优选 shutdown 来完成对连接一个方向的关闭,待对端处理完之后,再完成另外一个方向的关闭。
close 和 shutdown 的差别相关推荐
- Linux高并发服务器开发---笔记4(网络编程)
0705 第4章 项目制作与技能提升 4.0 视频课链接 4.1 项目介绍与环境搭建 4.2 Linux系统编程1.4.3 Linux系统编程2 4.4 多进程 1-9 10.进程间通信☆☆☆ 4.5 ...
- oracle实例名,数据库名,服务名等概念差别与联系
数据库名.实例名.数据库域名.全局数据库名.服务名 这是几个令非常多刚開始学习的人easy混淆的概念.相信非常多刚開始学习的人都与我一样被标题上这些个概念搞得一头雾水.我们如今就来把它们弄个明确. 一 ...
- 线程池shutdown和shutdownNow原理和区别
说明:以ThreadPoolExecutor线程池为例说明整个流程(不同的线程池实现上略有差别). 一.shutdown流程 1.流程简介 修改线程池状态为SHUTDOWN 不再接收新提交的任务 中断 ...
- 01033 oracle linux,ORA-01033:ORACLE initialization or shutdown in process
Oracle遇到问题 :在PL/SQL当输入用户名和密码后 竟然出现标题上错误,我一项目数据库数据库全都没有备份,还有很多很多数据,该不会让我重装数据库吧,想到这个我汗那个流啊. 在网上查了下 看了看 ...
- Linux的shutdown关机命令,Linux系统Shutdown命令定时关机详解
转自:http://www.bootf.com/490.html Linux系统下的shutdown命令用于安全的关闭/重启计算机,它不仅可以方便的实现定时关机,还可以由用户决定关机时的相关参数.在执 ...
- Executor - Shutdown、ShutdownNow、awaitTermination 详解与实战
一.引言 使用 executor 线程池时经常用到 shutdown / shutdownNow + awaitTermination 方法关闭线程池,下面看下几种方法的定义与常见用法. 二.API ...
- .pgr照片文件解析,C++与Java存储数据差别大小端模式
一..pgr是什么? .pgr文件是二进制的图像文件,可以用普通的文本文件打开,或者查看十六进制的文本信息: 读取需要了解~~~非常重要 !!! 基本数据类型的大小端存储模式 表头Header 详细信 ...
- C语言网络编程:close或者shutdown断开通信连接
文章目录 前言 close函数介绍 shutdown函数介绍 前言 这里在主要通过实例进行描述close函数在网络编程中的使用 TCP编程模型中客户端或者服务器只要主动通过close发起断开连接的请求 ...
- 堆和栈的差别(转过无数次的文章)
一.预备知识-程序的内存分配 一个由C/C++编译的程序占用的内存分为下面几个部分 1.栈区(stack)- 由编译器自己主动分配释放 ,存放函数的參数值,局部变量的值等.其 ...
- oracle initialization or shutdown in progress解决方法
今儿一直在测试服务器的迁移问题,不断地创建表空间.创建数据库.创建用户.后来感觉创建这么多东西太占用磁盘空间,心想删除一下吧,于是,我们执行了dbca命令,将没用的数据库统统删除,将dbf和dmp文件 ...
最新文章
- 如何在超大分辨率的图片中检测目标?
- [转]Pass a ViewBag instance to a HiddenFor field in Razor
- 安装apache服务出错,无法启动此程序,因为计算机中丢失VCRUNTIME140.dll 尝试重新安装此程序以解决此问题...
- mysql什么情况下使用索引
- 仿照vue实现简易的MVVM框架(一)
- 通过什么途径能够深入了解JavaScript引擎是如何工作的?
- 字符串类习题、面试题详解(第二篇)
- SpringBoot学习笔记(15):动态数据源切换
- 踩坑日记(一):半夜打DBA电话解决数据库连接超时自动回滚问题
- php位置,php – 如何有效地找到一个给定位置附近最近的位置
- 【Scratch案例实操】scratch西游记师徒谁人气高 scratch编程案例教学 scratch创意编程 少儿编程教案
- php is_subclass_of,PHP中的is_subclass_of()函数
- log日志:如何设置log级别、打印字体的颜色
- [二级域名映射端口][Ngins端口映射]腾讯云二级域名映射端口
- 【转】用生命之花制定自己的月计划
- 八爪鱼爬取列表数据和详情页数据(国内网址)
- SpringBoot-数据库连接池(java配置和Yaml配置)
- android动态毛玻璃,Android模糊处理实现图片毛玻璃效果
- python面向对象 : 反射和内置方法
- 一线互联网技术团队管理经验谈