假设server和client 已经建立了连接,server调用了close, 发送FIN 段给client(其实不一定会发送FIN段,后面再说),此时server不能再通过socket发送和接收数据,此时client调用read,如果接收到FIN 段会返回0,但client此时还是可以write 给server的,write调用只负责把数据交给TCP发送缓冲区就可以成功返回了,所以不会出错,而server收到数据后应答一个RST段,表示服务器已经不能接收数据,连接重置,client收到RST段后无法立刻通知应用层,只把这个状态保存在TCP协议层。如果client再次调用write发数据给server,由于TCP协议层已经处于RST状态了,因此不会将数据发出,而是发一个SIGPIPE信号给应用层,SIGPIPE信号的缺省处理动作是终止程序。

有时候代码中需要连续多次调用write,可能还来不及调用read得知对方已关闭了连接就被SIGPIPE信号终止掉了,这就需要在初始化时调用sigaction处理SIGPIPE信号,对于这个信号的处理我们通常忽略即可,signal(SIGPIPE, SIG_IGN); 如果SIGPIPE信号没有导致进程异常退出,write返回-1并且errno为EPIPE。

#include <unistd.h>
int close(int fd);

close 关闭了自身数据传输的两个方向。

close一个TCP套接字的默认行为是把该套接字标记成已关闭,然后立即返回到调用进程。该套接字描述符不能再由调用进程使用,也就是说它不能作为read或write的第一个参数。然而TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后发生的是正常的TCP连接终止序列。

我们可以通过SO_LINGER套接字选项可以用来改变TCO套接字的这种默认行为。

终止网络连接的通常方法是调用close函数。不过close有两个限制,却可以使用shutdown来避免。

(1)close把描述符的引用计数减1,仅在该计数变为0时才关闭套接字。使用shutdown可以不管引用计数就激发TCP的正常连接终止序列。

(2)close终止读和写两个方向的数据传送。既然TCP连接是全双工的,有时候我们需要告知对端我们已经完成了数据发送,即使对端仍然有数据要发送给我们。

#include <sys/socket.h>
int shutdown(int sockfd,int howto);
返回:若成功则为0,若出错则为-1

该函数的行为依赖于howto参数的值:

  • SHUT_RD    关闭连接的读这一半,套接字中不在有数据可接收,而且套接字接收缓冲区中的现有数据都被丢失。进程不能再对这样的套接字调用任何读函数。对一个TCP套接字这样调用shutdown函数后,由该套接字接收的来自对端的任何数据都被确认,然后悄然丢弃。
  • SHUT_WR    关闭连接的写这一半,对于TCP套接字,这称为半关闭。当前留在套接字发送缓冲区中的数据将被发送掉,后跟TCP的正常连接终止序列。我们已经说过了,不管套接字描述符的引用计数是否等于0,这样的写半部关闭照样执行。进程不能再对这样的套接字调用任何写函数。
  • SHUT_RDWR  连接的读半部和写半部都关闭,这与调用shutdown两次等效:第一次调用指定SHUT_RD,第二次调用指定SHUT _WR。

UNIX网络编程——shutdown 与 close 函数 的区别的更多相关文章

  1. UNIX网络编程——getsockname和getpeername函数

    UNIX网络编程--getsockname和getpeername函数   来源:网络转载   http://www.educity.cn/linux/1241293.html     这两个函数或者 ...

  2. UNIX网络编程——UDP 的connect函数(改进版)

    上一篇我们提到,除非套接字已连接,否则异步错误是不会返回到UDP套接字的.我们确实可以给UDP套接字调用connect,然而这样做的结果却与TCP连接大相径庭:没有三次握手.内核只是检查是否存在立即可 ...

  3. UNIX网络编程——send与recv函数详解

    #include <sys/socket.h> ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags); ssize_ ...

  4. UNIX网络编程学习指南--epoll函数

    epoll是select/poll的强化版,都是多路复用的函数,epoll有了很大的改进. epoll的功能 1.支持监听大数目的socket描述符 一个进程内,select能打开的fd是有限制的,有 ...

  5. Unix网络编程 3.9 readline函数

    其实看APUE时就想试着写些简单的stdio函数了,但是一直没实践,看到这里时发现书上写得不完整,便敲代码试了下. 第1个readline速度非常慢原因在于每次读取字符都执行了系统调用read(),而 ...

  6. Unix 网络编程 dup和dup2函数

    dup和dup2也是两个很实用的调用,它们的作用都是用来复制一个文件的描写叙述符. 它们经经常使用来重定向进程的stdin.stdout和stderr.这两个函数的原形例如以下: #include & ...

  7. unix网络编程str_cli使用epoll实现

    unix网络编程str_cli使用epoll实现 unix环境高级编程中也有这个函数,都是为了讲解IO多路转接.从本质上来看epoll就是一个改善了的select和poll,本质没发生任何变化,对于构 ...

  8. 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数

    本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...

  9. 《Unix 网络编程》14:高级 I/O 函数

    高级 I/O 函数 ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ...

随机推荐

  1. 给小白看的KMP算法

    浅谈KMP算法: (大部分人的KMP写法都是不一样的) 一: 先给大家推荐一个讲kmp特别好理解的一个博客:阮一峰 二: 再给大家介绍一点相关概念: 栗子:  P串: ABCBD 前缀:A,AB,AB ...

  2. 利用Runtime实现简单的字典转模型

    前言 我们都知道,开发中会有这么一个过程,就是将服务器返回的数据转换成我们自己定义的模型对象.当然服务器返回的数据结构有xml类型的,也有json类型的.本文只讨论json格式的. 大家在项目中一般是 ...

  3. Js删除数组函数

    引用地址:http://www.398588.com/Article/T8/96.aspx 众所周知大家都应该知道delete的用法,用来删除对象或者删除数组等,如果是删除对象除数组以外可能可以删除的 ...

  4. 嫌我的键盘的backspace太小,就尝试了一下改键工具--keyTweak

    KeyTweak是一个很简单的键盘remap小工具,主要功能就是可以让我们选择某个按键并重新赋予该按键一个新的功能.如果哪天你的键盘某个重要的键坏掉了,可以通过这个免费的软件来重新定义该按键的功能.譬 ...

  5. 02_Action

    1.action VS Action action:代表一个Struts2的请求 Action:能够处理action请求的类 属性名必须与JavaBeans属性名相同 属性的类型可以是任意类型,从字符 ...

  6. ACM Robot Motion

      机器人已被编程为按照其指令中的路径进行操作.机器人要移动的下一个方向的指令放在网格中.可能的指令是 N north (up the page) S south (down the page) E ...

  7. docker环境 快速使用elasticsearch-head插件

    docker环境 快速使用elasticsearch-head插件 #elasticsearch配置 #进入elk容器 docker exec -it elk /bin/bash #head插件访问配 ...

  8. md编辑器测试

    markdown 这是一个代码 print

  9. Android Studio NDK 代码 Source Insight调试 (NDK 目前开发方案 | NDK 编译 | 导入 so 库 | 项目编码转换)

    作者 : 韩曙亮 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/52088039 最近在移植一个 JNI 项目, 比较纠结, A ...

  10. Web自动化框架LazyUI使用手册(7)--浏览器常用操作API

      LazyUI框架中,BrowserEmulator类提供了大量的浏览器操作,常用的API列举如下: 1. 基本操作 /** * Open the URL * 打开一个URL * @param ur ...