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. 腾讯Web前端开发框架JX(Javascript eXtension tools)

    转自:Web前端开发-Web前端工程师 » 腾讯Web前端开发框架JX(Javascript eXtension tools) JX – Javascript eXtension tools 一个类似 ...

  2. leetcode665

    这道题目,主要是判断相邻的两个值的大小,并按照要求的方式,将数组的数值都修正为符合要求的值. 然后通过一次的遍历,计算所累积的移动次数. bool checkPossibility(vector< ...

  3. 【转】Android下面打印进程函数调用堆栈(dump backtrace)的方法

    1. 为什么要打印函数调用堆栈? 打印调用堆栈可以直接把问题发生时的函数调用关系打出来,非常有利于理解函数调用关系.比如函数A可能被B/C/D调用,如果只看代码,B/C/D谁调用A都有可能,如果打印出 ...

  4. DAY15-HTTP协议简述

    HTTP协议 一.HTTP协议简介 超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式.协作式和超媒体信息系统的应用层协议.HTTP是万维网 ...

  5. C#如何拿到从http上返回JSON数据?

    第一章:C#如何拿到从http上返回JSON数据? 第二章:C#如何解析JSON数据?(反序列化对象) 第三章:C#如何生成JSON字符串?(序列化对象) 第四章:C#如何生成JSON字符串提交给接口 ...

  6. JS中,根据div数值判断弹出窗口

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. python爬虫(6)--Requests库的用法

    1.安装 利用pip来安装reques库,进入pip的下载位置,打开cmd,默认地址为 C:\Python27\Scripts 可以看到文件中有pip.exe,直接在上面输入cmd回车,进入命令行界面 ...

  8. JAVA基础知识总结6(面向对象特征之一:多态)

    多 态:函数本身就具备多态性,某一种事物有不同的具体的体现. 体现:父类引用或者接口的引用指向了自己的子类对象. Animal a = new Cat(); 多态的好处:提高了程序的扩展性. 多态的弊 ...

  9. 201671010127 2016—2017—2 Java学习周结

    时间真是个最公平东西,只要能够好好地利用它,它可以为我们带来我们我们所想要的东西.学习Java已经有一周了,对于Java基础知识的认识也更进一步,对Java的兴趣也愈来愈浓.实现一个Java程序,主要 ...

  10. sql 一些偶尔会用到的写法和函数 不定时更新

    小数转整数: --round() 遵循四舍五入把原值转化为指定小数位数,如: ) -- =1 ) -- =2 --floor() 向下舍入为指定小数位数 如: SELECT floor(1.45) - ...