shutdown的定义

#include<sys/socket.h>
int shutdown(int sockfd,int how);

  how的方式有三种分别是:
    SHUT_RD(0):关闭sockfd上的读功能,此选项将不允许sockfd进行读操作。即该套接字不再接受数据,任何当前在套接字接受缓冲区的数据将被丢弃。进程将不能对该套接字发出任何读操作。对TCP套接字该调用之后接受到的任何数据将被确认然后无声的丢弃掉。
    SHUT_WR(1):关闭sockfd的写功能,此选项将不允许sockfd进行写操作,即进程不能在对此套接字发出写操作。
    SHUT_RDWR(2):关闭sockfd的读写功能,相当于调用shutdown两次:首先是以SHUT_RD,然后以SHUT_WR。

  成功则返回0,错误返回-1,错误码errno:EBADF表示sockfd不是一个有效描述符;ENOTCONN表示sockfd未连接;ENOTSOCK表示sockfd是一个文件描述符而不是socket描述符。

  shutdown()的效果是累计的,不可逆转的。既如果关闭了一个方向数据传输,那么这个方向将会被关闭直至完全被关闭或删除,而不能重新被打开。如果第一次调用了shutdown(0),第二次调用了shutdown(1),那么这时的效果就相当于shutdown(2),也就是双向关闭socket。

close的定义

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

  关闭读写。成功则返回0,错误返回-1,错误码errno:EBADF表示fd不是一个有效描述符;EINTR表示close函数被信号中断;EIO表示一个IO错误。

二者的区别

  close-----关闭本进程的socket id,但链接还是开着的,用这个socket id的其它进程还能用这个链接,能读或写这个socket id。
  shutdown--破坏了socket 链接,读的时候可能侦探到EOF结束符,写的时候可能会收到一个SIGPIPE信号,这个信号可能直到socket buffer被填充了才收到,shutdown有一个关闭方式的参数,0 不能再读,1不能再写,2 读写都不能。

socket 多进程中的 shutdown、close 的使用
  当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作:close(sockfd);使用close中止一个连接,但它只是减少描述符的参考数,并不直接关闭连接,只有当描述符的参考数为0时才关闭连接。所以在多进程/线程程序中,close只是确保了对于某个特定的进程或线程来说,该连接是关闭的。使用 client_fd = accept() 后 fork() 以在子进程中处理请求,此时在父进程中使用 close() 关闭该连接,子进程仍可以继续使用该连接

  也可以调用shutdown()函数来关闭该socket。该函数允许你只停止在某个方向上的数据传输,而一个方向上的数据传输继续进行。如你可以关闭某socket的写操作而允许继续在该socket上接受数据,直至读入所有数据。int shutdown(int sockfd,int how);shutdown可直接关闭描述符,不考虑描述符的参考数,可选择中止一个方向的连接。

注意
  1.如果有多个进程共享一个套接字,close每被调用一次,计数减1,直到计数为0时,也就是所用进程都调用了close,套接字将被释放。

  2.在多进程中如果一个进程中shutdown(sfd, SHUT_RDWR)后其它的进程将无法进行通信。如果一个进程close(sfd)将不会影响到其它进程,得自己理解引用计数的用法了。有Kernel编程知识的更好理解了.

更多关于close和shutdown的说明
  1.只要TCP栈的读缓冲里还有未读取(read)数据,则调用close时会直接向对端发送RST

  2.shutdown与socket描述符没有关系,即使调用shutdown(fd, SHUT_RDWR)也不会关闭fd,最终还需close(fd)

  3.可以认为shutdown(fd, SHUT_RD)是空操作,因为shutdown后还可以继续从该socket读取数据,这点也许还需要进一步证实。在已发送FIN包后write该socket描述符会引发EPIPE/SIGPIPE。

  4.当有多个socket描述符指向同一socket对象时,调用close时首先会递减该对象的引用计数,计数为0时才会发送FIN包结束TCP连接。shutdown不同,只要以SHUT_WR/SHUT_RDWR方式调用即发送FIN包。

  5.SO_LINGER与close,当SO_LINGER选项开启但超时值为0时,调用close直接发送RST(这样可以避免进入TIME_WAIT状态,但破坏了TCP协议的正常工作方式),SO_LINGER对shutdown无影响。

  6.TCP连接上出现RST与随后可能的TIME_WAIT状态没有直接关系,主动发FIN包方必然会进入TIME_WAIT状态,除非不发送FIN而直接以发送RST结束连接

应用场景

  通常来说,socket是双向的,即数据是双向通信的。但有些时候,你会想在socket上实现单向的socket,即数据往一个方向传输。单向的socket便称为半开放Socket。要实现半开放式,需要用到shutdown()函数。

  一般来说,半开放socket适用于以下场合:
    1.当你想要确保所有写好的数据已经发送成功时。如果在发送数据的过程中,网络意外断开或者出现异常,系统不一定会返回异常,这是你可能以为对端已经接收到数据了。这时需要用shutdown()来确定数据是否发送成功,因为调用shutdown()时只有在缓存中的数据全部发送成功后才会返回。

    2.想用一种方法来捕获程序潜在的错误,这错误可能是因为往一个不能写的socket上写数据,也有可能是在一个不该读操作的socket上读数据。当程序尝试这样做时,将会捕获到一个异常,捕获异常对于程序排错来说是相对简单和省劲的。

    3.当您的程序使用了fork()或者使用多线程时,你想防止其他线程或进程访问到该资源,又或者你想立刻关闭这个socket,那么可以用shutdown()来实现。

参考

  http://blog.csdn.net/pingnanlee/article/details/8426712

  http://blog.csdn.net/moxiaomomo/article/details/7897943

Linux-socket的close和shutdown区别及应用场景的更多相关文章

  1. Linux Socket 编程简介

    在 TCP/IP 协议中,"IP地址 + TCP或UDP端口号" 可以唯一标识网络通讯中的一个进程,"IP地址+端口号" 就称为 socket.本文以一个简单的 ...

  2. linux socket高性能服务器处理框架

    这个博客很多东西 http://blog.csdn.net/luozhonghua2014/article/details/37041765   思考一种高性能的服务器处理框架 1.首先需要一个内存池 ...

  3. OpenFastPath(2):原生态Linux Socket应用如何移植到OpenFastPath上?

    版本信息: ODP(Open Data Plane): 1.19.0.2 OFP(Open Fast Path): 3.0.0 1.存在的问题 OpenFastPath作为一个开源的用户态TCP/IP ...

  4. Linux Socket - 基本socket链接

    0x0000 Linux Socket 函数 bind listen connect accept send recv read write 0x0001 Server绑不上ip 报错位置在bind函 ...

  5. Linux socket 编程中存在的五个隐患

    前言:         Socket API 是网络应用程序开发中实际应用的标准 API.尽管该 API 简单,但是   开发新手可能会经历一些常见的问题.本文识别一些最常见的隐患并向您显示如何避免它 ...

  6. JAVA Socket API与LINUX Socket API探究

    代码 这是一个带有UI界面的JAVA网络聊天程序,使用Socket连接完成通信. JAVA服务端程序 import java.io.IOException; import java.io.InputS ...

  7. Linux Kernel: buffers和cached的区别

    The page cache caches pages of files to optimize file I/O. The buffer cache caches disk blocks to op ...

  8. Linux read/write fread/fwrite两者区别

    Linux read/write fread/fwrite两者区别 1,fread是带缓冲的,read不带缓冲. 2,fopen是标准c里定义的,open是POSIX中定义的. 3,fread可以读一 ...

  9. Linux socket编程 DNS查询IP地址

    本来是一次计算机网络的实验,但是还没有完全写好,DNS的响应请求报文的冗余信息太多了,不只有IP地址.所以这次的实验主要就是解析DNS报文.同时也需要正确的填充请求报文.如果代码有什么bug,欢迎指正 ...

随机推荐

  1. Spiral Matrix leetcode java

    题目: Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spira ...

  2. js改变iframe 的src地址

    <script> function dizhi(){ document.getElementById("aaa").src='http://www.sohu.com' ...

  3. MFC中设备描述表dc的使用

    以下代码我是在View类中实现的: /** 利用平台SDK实现画线功能 // 首先获得窗口的设备描述表 HDC hdc; hdc = ::GetDC( m_hWnd ); //调用的是平台SDK的成员 ...

  4. Java 读取某个目录下所有文件、文件夹

    /** * @Author: * @Description:获取某个目录下所有直接下级文件,不包括目录下的子目录的下的文件,所以不用递归获取 * @Date: */ public static Lis ...

  5. laravel在中间件内生成的变量如何传到控制器

    在中间件内获取到一个变量,如何返回到控制器中并使用这个变量! 做了个demo: // web.php Route::get('/check', 'CheckController@check')-> ...

  6. Android -- Serializable和Parcelable需要注意的

    Serializable 静态变量序列化不会被保存 public class Test implements Serializable { private static final long seri ...

  7. 前端笔记----jquery入门知识点总结 (转)

    http://www.cnblogs.com/cwp-bg/p/7633623.html 一.jquery的加载方法 $(document).ready(function(){js代码}); $(fu ...

  8. 你应该知道的Linux历史

    说道linux的历史不得不说的就是unix,我们的linux就是类unix系统: 1969年第一台unix系统 贝尔实验室 1970年C语言诞生,对unix内核重新编写 system V(AT& ...

  9. oauth2-server-php-docs 存储 学说2

    学说2 创建客户端和访问令牌存储 要把学说融入到你的项目中,首先要建立你的实体.我们先从客户端,用户和访问令牌模型开始: yaml YourNamespace\Entity\OAuthClient: ...

  10. javascript高级语法学习

    可维护的代码意味着: 可读的 一致的 可预测的 看上去就像是同一个人写的 已记录 命名函数表达式 (function fn(){}) 他是表达式的原因是因为括号 ()是一个分组操作符,它的内部只能包含 ...