socket关闭: close()和shutdown()的差异

对于一个tcp连接,在c语言里一般有2种方法可以将其关闭:

close(sock_fd);

或者

shutdown(sock_fd, ...);

多数情况下这2个方法的效果没有区别,可以互换使用。除了:

close() 是针对file的操作

shutdown() 是针对socket的操作

nix系统里socket是1个文件,但文件不1定是1个socket;

所以在进入系统调用后和达到协议层前(发出FIN包这一段), close()和shutdown()的行为会有1点差异。

到达协议层以后,close()和shutdown()没有区别。

举几个栗子示范下close()和shutdown()的差异

下面通过几个例子演示下close()和shutdown()在多线程并发时的行为差异, 我们假设场景是:

sock_fd 是一个blocking mode的socket。

thread-1 正在对sock_fd进行阻塞的recv(),还没有返回。

thread-2 直接对sock_fd调用close() 或 shutdown()。

不考虑linger。

栗子1: socket阻塞在recv()上, 调用close()

// Close a waiting recv()

Time

|

| thread-1 | thread-2 | tcpdump

| | |

| recv(sock_fd | |

| | |

1| | close(sock_fd) = 0 |

| | | // Some data arrived

| | | // after close()

2| | | < seq 1:36 ... length 35

| | | > ack 36 ...

| // Data was received. | |

3| <... recv resumed>) = 35 | |

4| | | > FIN sent

| | | < ack of FIN received

| | | ...

| // Can't be used any more | |

5v recv(sock_fd)= -1 | |

在上面的例子里:

(1) thread-2 调用close()立即成功返回,这时recv()还在使用sock_fd。

这里因为有另外1个线程thread-1正在使用sock_fd, 所以只是标记这个sock_fd为要关闭的。 socket并没有真正关闭。

这时recv()还继续处于阻塞读取状态。

(2) close()之后,有些数据到了,recv可以读取并返回了。

(3) recv()收到数据, 正确退出。

(4) rece()结束调用,释放socket的引用,这时底层开始关闭socket的流程。

(5) 再次调用recv()就会得到错误。

可以看到,close()没有立即关闭socket的连接,也没有打断等待的recv()。

栗子2: socket阻塞在recv()上, 调用shutdown()

// Shutdown a waiting recv()

Time

|

| thread-1 | thread-2 | tcpdump

| | |

| recv(sock_fd | |

| | |

1| | shutdown(sock_fd) = 0 | > FIN sent

| | | < ack of FIN received

| | | ...

| // Woken up by shutdown() | |

| // no errno set | |

2| <... recv resumed>) = 0 | |

v | |

在上面的例子里:

(1) thread-1还在等待sock_fd, thread-2调用shutdown(), 立即开始关闭socket的流程,发FIN 包等。

然后, 内核中tcp_shutdown中会调用sock_def_wakeup 唤醒阻塞在recv()上的thread-1。

(2) 这时recv()阻塞的线程被唤醒等待并立即返回。 返回码是0,表示socket已经关了。

可以看到,shutdown()和close()不同, 会立即关闭socket的连接,并唤醒等待的recv()。

以上2个例子的代码

close-or-shutdown-recv

栗子3: socket阻塞在accept()上, 调用shutdown()

类似的,对阻塞在accept()上的socket调用shutdown(),accept也会被唤醒:

// Shutdown a waiting accept()

Time

|

| thread-1 | thread-2

c语言 socket 断开自动连接,如何优雅地断开TCP连接?相关推荐

  1. 连接服务器_服务器海量TCP连接如何高效保活?

    在互联网领域,客户端和服务端之间通常需要建立和保持TCP长连接.所谓长连接,就是通信双方在建立TCP连接后进行数据通信,一次或若干次通信交互完成之后,不主动断开连接,而是保持TCP连接不释放,在随时需 ...

  2. linux限制单个ip频繁连接,限制单个IP并发TCP连接的方法

    限制单个IP并发TCP连接的方法适应于保护Linux上的各种TCP服务,使用iptables 中patch-o-matic中iplimit补丁来实现,对各种TCP服务比较通用. 做法: 配置Linux ...

  3. 网络七层协议 五层模型 TCP连接 HTTP连接 socket套接字

    socket(套接字)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程 ...

  4. TCP三次握手建立连接四次挥手断开连接

    仅用于做笔记,转载自https://blog.csdn.net/whuslei/article/details/6667471 首先Client端发送连接请求报文,Server段接受连接后回复ACK报 ...

  5. TCP连接三次握手和四次挥手

    摘要: 本文主要介绍TCP连接三次握手和四次挥手的机制. 1.三次握手 (1)三次握手的详述 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源.Clie ...

  6. TCP协议-TCP连接管理

    一.TCP概述 TCP协议是 TCP/IP 协议族中一个非常重要的协议.它是一种面向连接.提供可靠服务.面向字节流的传输层通信协议. TCP(Transmission Control Protocol ...

  7. TCP连接的3次握手和4次挥手

    三次握手: 3次握手的过程如下: 第一次握手:起初两端都处于CLOSED关闭状态,Client将标志位SYN置为1,随机产生一个值seq=x,并将该数据包发送给Server,Client进入SYN-S ...

  8. 你知道 HTTP 是如何使用 TCP 连接的吗?今天我就来告诉你!

    之前我写了篇关于 HTTP 的文章,文章中讲述了 HTTP 的特点,HTTP 的报文,HTTP 的请求方式等知识,接下来,深入了,我们就关于 HTTP 引发的面试题来进行入手,一起来看一下吧! 1.H ...

  9. 拔掉网线后, 原本的 TCP 连接还存在吗?

    大家好,我是小林. 今天,聊一个有趣的问题:拔掉网线几秒,再插回去,原本的 TCP 连接还存在吗? 可能有的同学会说,网线都被拔掉了,那说明物理层被断开了,那在上层的传输层理应也会断开,所以原本的 T ...

最新文章

  1. swift视图容器_如何使用IBDesignable在Swift中创建漂亮的,可重复使用的渐变视图...
  2. 【土地评价与土地管理】教案 第一章:土地评价要素的选择
  3. 小甲鱼 OllyDbg 教程系列 (一) :二进制破解科普系列之 ReverseMe
  4. 多用途app软件业务介绍官网模板
  5. 使用NUnit在.Net编程中进行单元测试(转载)
  6. OLAP工具在企业决策支持系统中的应用
  7. 手机数据恢复软件哪个好用?
  8. 计算机字节换算在线,计算机字节换算(计算机字节换算器)
  9. 2.3两个列表或元组首尾相连
  10. MAC10.11 Python3.6 安装Scrapy
  11. Harfbuzz version too old (1.2.1)
  12. python压缩_Python札记 -- 文件压缩
  13. Origin 2017调整画布和图表的尺寸大小
  14. win10如何置顶某个窗口
  15. 萌新如何用板绘画好原画?怎么选择数位板?零基础板绘入门干货篇
  16. 一些离谱的化学方程式
  17. Ubuntu左手鼠标指针
  18. 【预测模型】基于BP神经网络预测价格matlab代码
  19. [LBS学习笔记 1]高德数据可视化初体验
  20. 个人实战经验分享-虚拟产品的几种零基础起步赚钱玩法

热门文章

  1. 80-30-010-原理-React模式-简介
  2. 【elasticsearch】Elasticsearch 7.X Scripting 脚本使用详解
  3. 【jvm】java jvm 报错 OutOfMemoryError: GC overhead limit exceeded
  4. 【MySQL】MySQL常见的读写分离方法
  5. maven编译:target/surefire-reports for the individual test results
  6. python excel数据框_python – 熊猫数据框到Excel表
  7. 反射和多态的实现原理详解以及区别
  8. SpringCloud+Docker+Jenkins+GitLab+Maven实现自动化构建与部署实战
  9. linux中循环创建文件,linux-尝试创建一个文件以调用另一个文件进行循环搜索
  10. WebStorm生成Vue的组件关系图