1.close()函数:立即返回到进程

int close(int sockfd);     //返回成功为0,出错为-1.

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

在多进程并发服务器中,父子进程共享着套接字,套接字描述符引用计数记录着共享着的进程个数,当父进程或某一子进程close掉套接字时,描述符引用计数会相应的减一,当引用计数仍大于零时,这个close调用就不会引发TCP的四路握手断连过程。

(假设服务器server端调用close)

如果server的socket套机字的接收缓冲区,还有数据未被应用进程读取,则server直接发送RST报文给client。

如果接收缓冲区没有数据了,但是发送缓冲区还有数据未被发送,则会尝试先发送此部分数据,然后才是发送FIN报文。

通过设置SO_LINNGER套接字口选项,可以改变缺省的功能。

struct linger {
    int onoff; /* 0=off, nonzero=on */
    int l_linger; /* linger time, POSIX specifies units as seconds */
};

1. close后,默认情况与使用l_onoff=0效果一致,本方继续接收数据并ACK,但会丢弃这些数据,直到对方FIN过来,完成连接终止过程;
2. close后,l_onoff非0且l_linger=0,立即丢弃发送缓存区数据并给对方发送一个RST,也就是不会有正常的四分组终止过程,也没有TIME_WAIT,对方收到RST后,肯定不能继续发数据了;
3. close后,l_onoff非0且l_linger>0,设置拖延时间,内核拖延,close会等待l_linger(阻塞情况下),两种可能,在延迟时间到达之前,数据发送完毕且被对方确认,或者延迟时间到了,通过进程检查close返回值判别,是那种情况,若是第二种,而返回ewouldbloack,且发送缓冲区的所有数据都丢失。

只要l_onoff为0,无论l_linger为什么值,都跟缺省情况完全一样

如果close造成的是发送FIN,在这之后,对方继续发送data 过来的话呢?
按照底层TCP协议,local侧是否继续发送ack of data给对方,直到local侧buffer满了
因为TCP两方的通信通道,local侧永远只能掌控local侧出去的方向,不能控制对方侧继续发送数据。即在FIN_WAIT2状态时,local侧依然可以接收对方的data

注意:缺省的情况下,server close(fd),且发送FIN给client之后,client端还是可以发送数据给server,只是server只是接收client发送到接收缓冲区的数据,然后全部丢失,也不应答。

2、shutdown()函数

int shutdown(int sockfd,int howto);  //返回成功为0,出错为-1

shut_rd:关闭读这一半,在接收缓冲区的数据全部丢失,进程不能对此socket执行任何读操作,但是对方还是可以发送数据到此socket的接收缓冲区,且发送应答ack,只是接收缓冲区的数据全部丢失

shut_wr:关闭写一半,当前在发送缓冲区的数据首先被发送,然后才是FIN报文(这跟close一样),但是此函数不管套接字描述符的引用计数是否为0,都会执行操作,这根close不同。

两者之间比较:
close和shutdown的行为取决于内核的实现。
1. close调用之后如果在local TCP buffer内如果还有数据没有读取会给对方直接回RST, 否则发送FIN,这取决于调用close时刻local TCP buffer的状态, 跟对端是不是继续发送数据无关。
2. shutdown关闭读不会给对方发FIN, 只有关闭写才会发FIN, 而且跟local TCP buffer状态没关系,只发送FIN包,从不发送RST

设置l_onoff为非0,l_linger为非0,那么一种可能的情况是,在延迟时间到达之后,收到数据确认和FIN确认,此时close才返回,这告诉我们,发送的数据和FIN都被对方确认了。但是他不能告诉我们,数据是否被对方应用进程读取。但是不设置这个选项,连对方TCP是否确认了数据都不知道。

让client知道server读取了其数据的解决方法:

调用shutdown,之后read堵塞,直到对方的FIN发来(因为对方应用层读取数据和FIN之后,调用close),read才返回0.

socket 释放全过程的更多相关文章

  1. 二. Socket用法

    C/S通信架构中,客户端要主动与服务端建立连接,这个链接就是Socket套接字.服务端收到连接请求后,也会开启Socket记录与客户端的链接.C/S两端都要建路Socket才能正常收发数据. 一.构造 ...

  2. SO_REUSEADDR和SO_REUSEPORT异同

    文章内容来源于stackoverflow上的回答,写的很详细http://stackoverflow.com/questions/14388706/socket-options-so-reuseadd ...

  3. tcp_tw_recycle和tcp_timestamps的文章汇总

        临近年关,人会变得浮躁,期间写的代码可谓乱七八糟.不过出来混始终是要还的,这不最近就发现一个PHP脚本时常连不上服务器. 遇到这类问题,我习惯于先用strace命令跟踪了一下看看: shell ...

  4. hibernate 3.* C3P0配置 以及为什么需要连接池!

    Hibernate自带的连接池算法相当不成熟. 它只是为了让你快些上手,并不适合用于产品系统或性能测试中. 出于最佳性能和稳定性考虑你应该使用第三方的连接池.只需要用特定连接池的设置替换 hibern ...

  5. 消息队列NetMQ 原理分析3-命令产生/处理和回收线程

    消息队列NetMQ 原理分析3-命令产生/处理和回收线程 前言 介绍 目的 命令 命令结构 命令产生 命令处理 创建Socket(SocketBase) 创建连接 创建绑定 回收线程 释放Socket ...

  6. Linux内核中网络数据包的接收-第一部分 概念和框架

    与网络数据包的发送不同,网络收包是异步的的.由于你不确定谁会在什么时候突然发一个网络包给你.因此这个网络收包逻辑事实上包括两件事:1.数据包到来后的通知2.收到通知并从数据包中获取数据这两件事发生在协 ...

  7. 【转】tcp_tw_recycle和tcp_timestamps导致connect失败问题

    (2012-02-01 18:40:32)     近来线上陆续出现了一些connect失败的问题,经过分析试验,最终确认和proc参数tcp_tw_recycle/tcp_timestamps相关: ...

  8. UDP收/发广播包原理及步骤

    原文链接地址:http://www.2cto.com/net/201311/254834.html UDP收/发广播包原理及步骤 如果网络中两个主机上的应用程序要相互通信,其一要知道彼此的IP,其二要 ...

  9. 浅析套接字中SO_REUSEPORT和SO_REUSEADDR的区别

    Socket的基本背景 在讨论这两个选项的区别时,我们需要知道的是BSD实现是所有socket实现的起源.基本上其他所有的系统某种程度上都参考了BSD socket实现(或者至少是其接口),然后开始了 ...

随机推荐

  1. RabbitMQ 消息队列 安装及使用

    RabbitMQ 消息队列安装: linux版本:CentOS 7 安装第一步:先关闭防火墙 1.Centos7.x关闭防火墙 [root@rabbitmq /]# systemctl stop fi ...

  2. jenkins基础知识

    修改默认端口号启动: java -jar jenkins.war --ajp13Port=-1 --httpPort=8089 一些基本的命令: http://[jenkins-server]/[co ...

  3. 10-13C#语句(1)

    C#语句:判断.循环.形成程序的分支和循环 1.语句分类 1)顺序语句 2)分支语句 3)循环语句 2.语句 选择控制:if,else,switch,case 循环控制:while,do,for,fo ...

  4. [patl2-020]功夫传人

    解题关键:dfs的简单应用,需要注意类型double与int #include<cstdio> #include<cstring> #include<algorithm& ...

  5. PHP的count(数组)和strlen(字符串)的内部实现

    PHP的count(数组)和strlen(字符串)的内部实现上是直接显示一个长度变量,还是重头依次数一遍有多少个元素?关乎我理解这2个函数的效率..希望高人能从php的c源码上讲一讲.没有源码看过源码 ...

  6. Python_pip_01_pip的相关操作

    >Python中的pip是什么?能够做些什么? pip是Python中的一个进行包管理的东西,能够下载包.安装包.卸载包......一些列操作 >怎么查看pip的相关信息 在控制台输入: ...

  7. 解析IFC数据并存储到关系型数据库

    即系IFC数据并存储到关系型数据库中,目前解析的IFC文件是两亿多行,构件数量120万

  8. js实现上传单个文件

    js上传文件:js 上传单个文件(任意大小) 疯狂代码 http://www.CrazyCoder.cn/ :http:/www.CrazyCoder.cn/Javascript/Article832 ...

  9. ARC102D All Your Paths are Different Lengths

    传送门 题目大意 让你构造一个有向图,使得从1到n有L条不同路径且长度分别是0~L-1. 分析 我们不难想到每一对相邻点之间连一条权值为0的边,之后二进制分解,将每一对点之间连一个权值为2^i的边,但 ...

  10. poj2287 Tian Ji -- The Horse Racing

    传送门 分析 这个题和传统的田忌赛马不一样的地方就是多了平局情况,所有我们不难想到要用dp.我们先将两人的马均降序排列,用dpij表示考虑前i匹马,田忌有几匹马是按从大到小的顺序从头取的(剩下的是从尾 ...