IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 网络编程--优雅关闭连接 -> 正文阅读

[网络协议]网络编程--优雅关闭连接

网络编程中,当一段发送完数据,想要关闭连接时,一般调用close().但close是不“优雅”的,首先看一下close()到底执行了什么。

首先应清楚一点,TCP虽然是基于字节流的传输,但是TCP模块为了提高发送和接收效率,会将字节流分段打包,也就是我们常说的TCP数据包;但是这样会使得一个包内的数据并不一定是一条完整的消息,所以需要编号来完成拼接(由seq,ack完成同步)。

一、close函数

以服务端调用close(sockfd)为例:
close()会立即返回,使得sockfd的引用计数减1,当前进程不能再调用有关socket读写的API,TCP模块会继续将TCP发送缓冲区中的数据尽力发送至对端。
若sockfd的引用计数为0(多进程fork会增加引用计数),则在TCP缓冲区数据发送完后会向对端发送FIN,进行四次挥手,TCP断开连接的过程;若引用计数不为0,则不会发送FIN,所以也不会断开连接,适用于父子进程共享连接套接字的情况。借用UNP里的一张图片说明当描述符引用为0时的情况:

在这里插入图片描述

SO_LINGER套接字选项

二、shutdown函数

int shutdown(int sockfd, int howto);

shutdown函数是用来终止连接的,而不是关闭套接字。
shutdown和close的区别
(1)close将描述符引用减1,为0时才关闭套接字;而shutdown直接触发TCP的正常终止序列(发送FIN包)
(2)之所以说close不够优雅,是因为当引用计数为0时,close关闭套接字直接返回,即使TCP发送缓冲区还有数据未发送完毕,即使TCP接收缓冲区还有数据未读取完毕(这种情况较少,一般都是read完毕后才调用close),即使对端还有数据要发送过来。假设服务端调用close且未设置LINGER,close立即返回,虽然TCP模块会尽可能发送,但服务端无法确认对方进程是否完整收到数据。若客户端在还未接收完数据时就崩溃(发送FIN包),服务器进程却无法知道(因为close返回,无法调用套接字相关API)
而shutdown通过howto参数来关闭指定方向的连接,howto的方式有三种分别是:
SHUT_RD:关闭sockfd上的读功能,此选项将不允许sockfd进行读操作。
SHUT_WR:关闭sockfd的写功能,此选项将不允许sockfd进行写操作。
SHUT_RDWR:关闭sockfd的读写功能。
为了优雅关闭连接,我们需要确认发送缓冲区数据确实已被对方接收到,且仍能够接收对方发送的数据。
常用的为SHUT_WR,下面详细介绍关闭写端的过程,借用UNP中一张图(图中客户端和服务端和以上我的假设相反,不过不影响)
在这里插入图片描述

更多关于close和shutdown的说明:
1 只要TCP栈的读缓冲里还有未读取(read)数据,则调用close时会直接向对端发送RST。
2. shutdown与socket描述符没有关系,即使调用shutdown(fd, SHUT_RDWR)也不会关闭fd,最终还需close(fd)。
3. 在已发送FIN包后write该socket描述符会引发EPIPE/SIGPIPE。
4. SO_LINGER与close,当SO_LINGER选项开启但超时值为0时,调用close直接发送RST(这样可以避免进入TIME_WAIT状态,但破坏了TCP协议的正常工作方式),SO_LINGER对shutdown无影响。
5. TCP连接上出现RST与随后可能的TIME_WAIT状态没有直接关系,主动发FIN包方必然会进入TIME_WAIT状态,除非不发送FIN而直接以发送RST结束连接。
6.避免TIME_WAIT更常用的是使用REUSEADDR选项

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-23 17:02:36  更:2021-08-23 17:04:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 20:21:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计