socket链接的关闭连接与close和shutdown的区别

TCP主动关闭连接 
appl: close(),  --> FIN     FIN_WAIT_1 //主动关闭socket方,调用close关闭socket,发FIN                         
                <-- ACK     FIN_WAIT_2 //对方操作系统的TCP层,给ACK响应。然后给FIN                  
                <-- FIN                  
                --> ACK     "TIME_WAIT"   -- 2MSL timeout -->CLOSED
                                        //TIME_WAIT,防止ACK没有给到对方。
注意:close时,如果TCP发送队列中还有数据,那么将会发送RST包而不是FIN包。
参看:http://rdc.taobao.com/blog/cs/?p=1055
另外:对于Linux下来说,无论是FIN还是RST,应用层read将会返回0,可以认为对方请求关闭链接,调用close关闭fd即可。
TCP被动关闭连接 
            <-- FIN     "CLOSE_WAIT"   //被动方,收到对方的FIN,处于CLOSE_WAIT状态                  
                --> ACK                    //被动方的TCP层,给ACK响应  
                appl: close(),  --> FIN     LAST_ACK      
                                         //被动方调用close,从CLOSE_WAIT转到LAST_ACK
                                         不调close,将一直在CLOSE_WAIT状态。                 
                 <-- ACK         --> CLOSED  
tcp是全双工::
   close()会关闭读写。
   shutdown()可以选择性的关闭读、写或读写。 
 
  主动关系SOCKET链接的一方,会进入TIME_WAIT(作用是防止最后一个ACK包丢失)
   TIME_WAIT的时间会非常长,因此server尽量减少主动关闭连接。
 
close和shutdown的区别:
   int close(int sockfd);   

close(fd)调用会将描述字的引用计数减1,只有当socket描述符的引用计数为0时,才关闭socket,即发送FIN包,因此,在fork()模式中,父进程在accept()返回后,fork()子进程,由子进程处理connfd,而父进程将close(connfd);由于connfd这个socket描述符的引用计数不为0,因此并不引发FIN,所以就没有关闭和客户端的连接。

  int shutdown(int sockfd, int howto);    
  // howto: SHUT_RD, SHUT_WR, SHUT_RDWR  
  shutdown()则不管socket描述符的引用计数,而直接发生FIN,因此会直接关闭链接。 
  shutdown()可控制read/write两个方向的管道。 
   SHUT_RD     shutdown(sockfd, SHUT_RD);后,来自对端的数据都被确认,然后悄然丢弃。       
   SHUT_WR     half close状态。  
close()引发的4次交互:(这里的close是client发起的) 
            client                             server  
               FIN_WAIT_1   ---- FIN M ------>       
                                       //(Server端操作系统的TCP层(网络协议栈)响应ACK包)           
               FIN_WAIT_2   <---- ACK M+1----   CLOSE_WAIT
                                       //(这里必须调用close,才能从CLOSE_WAIT到LAST_ACK)                  
               TIME_WAIT    <------ FIN N -----  LAST_ACK 
                                        //(TIME_WAIT有一个重要的作用就是防止最后一个ACK丢失)           
                            ------- ACK N+1 ---->  CLOSE  
 

TIME_WAIT 是主动关闭链接时形成的,等待2MSL时间,约4分钟。

主要是防止最后一个ACK丢失。  由于time_wait的时间会非常长,因此server端应尽量减少主动关闭连接

CLOSE_WAIT是被动关闭链接是形成的 ,

按状态机,我方收到FIN,则由TCP实现发送ACK,因此进入CLOSE_WAIT状态。

但如果我方不执行close(),就不能由CLOSE_WAIT迁移到LAST_ACK,则系统中会存在很多CLOSE_WAIT状态的连接。

此时,可能是系统忙于处理读、写操作,而未将已收到FIN的连接,进行close。此时,recv/read已收到FIN的连接socket,会返回0。

大量TIME_WAIT和CLOSE_WAIT的存在,会产生怎样的影响?

内核维护更多的状态。收到ip包,做hash运算,hlist冲突的概率更大。

另附一篇关于断开讲解很详细的文章

https://www.cnblogs.com/felixzh/p/8359066.html

原文地址:https://www.cnblogs.com/wangshaowei/p/11068494.html

时间: 2024-11-09 02:08:17

socket链接的关闭连接与close和shutdown的区别的相关文章

TCP三次握手(建立连接)/四次挥手(关闭连接)

相对于SOCKET开发者,TCP创建过程和链接折除过程是由TCP/IP协议栈自动创建的.因此开发者并不需要控制这个过程.但是对于理解TCP底层运作机制,相当有帮助. 而且对于有网络协议工程师之类笔试,几乎是必考的内容.因此在这里详细解释一下这两个过程. TCP数据包格式 顺序号( 32 位):用来标识从 TCP 源端向 TCP 目的端发送的数据字节流,它表示在这个报文段中的第一个数据字节的顺序号.如果将字节流看作在两个应用程序间的单向流动,则TCP用顺序号对每个字节进行计数.序号是32bit的无

关闭连接:本质是取消 Channel 在 Selelctor 的注册

关闭连接:本质是取消 Channel 在 Selelctor 的注册 目录 关闭连接:本质是取消 Channel 在 Selelctor 的注册 1. 主线分析 1.1 主线 1.2 知识点 2. 源码分析 2.1 read 2.2 close Netty 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) 1. 主线分析 1.1 主线 关闭连接分两种:主动关闭(正常关闭)和被动关闭(异常关闭). 多路复用器(Selector)接收到

boost::asio 连接管理11 如何关闭连接

在实际产品运行中,对连接管理有了更新的认识,这里分享一下. shared_ptr管理连接对象的生命周期 shared_ptr的引用计数器决定了连接对象的生命周期.这里我说的连接对象就是在我的前文:http://blog.csdn.net/csfreebird/article/details/8522620 中的Client对象: [cpp] view plaincopyprint? #include "core/connection.h" #include <vector>

关于TCP主动关闭连接中的wait_timeout

首先我们先来回顾一下tcp关闭连接的过程: 假设A和B连接状态为EST,A需要主动关闭: A发送FIN给B,并将状态更改为FIN_WAIT1, B接收到FIN将状态更改为CLOSE_WAIT,并回复ACK和FIN A收到ACK后将状态更改为FIN_WAIT2,收到FIN后,更改状态为WAIT_TIMEOUT并给B返回ACK B收到ACK后,将关闭自己的链接CLOSE. 问题就在此时,A将处于WAIT_TIMEOUT状态长达2MSL时常(RFC793定义了MSL为2分钟,Linux设置成了30s)

TCP建立连接的3次握手和关闭连接的4次挥手

#.3次握手过程状态 第一次握手:建立连接时,客户端发送SYN包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器 进入SYN_RECV状态: 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED状态,完成三次握手. 通过这样的三次握手,客

PHP Socket(套接字连接)扩展简介和使用方法

PHP socket扩展是基于流行的BSD sockets,实现了和socket通讯功能的底层接口,它可以和客户端一样当做一个socket服务器. 使用这些函数时请注意,虽然他们中有很多和C函数同名的,但声明却很可能不同.未避免混淆,请仔细阅读函数描述. 不熟悉socket编程的可以在Unix手册上找到很多有用的信息,网上也有很多C socket编程方面的教程,简单修改一下就可以应用于PHP socket编程. 第一步:开启socket 到php.ini开启extension=php_socke

Java设置Client Socket链接Server超时时间

Java设置Client Socket链接Server超时时间 学习了:http://blog.csdn.net/tterminator/article/details/52494141 http://blog.csdn.net/fw0124/article/details/41227543 整理如下: Socket client = null; // 创建一个流套接字,连接到指定主机上的指定端口号 // client = new Socket(IP, PORT); client = new S

crawler_http关闭连接

1:ps aux|grep Spider4Test.jar 查看端口 2: lsof  -p [端口号] 在爬虫运行期间如果看到 大量的 TIME_WAIT  WAIT_CLOSE 说明请求关闭阻塞[采用httpclient默认方法 ,其实没有关闭掉,需要跑等3分钟 才会关闭] 大量并发时   会有阻塞 3: 解决方法 最简单方法[方法四: 代码实现很简单,所有代码就和最上面的事例代码一样.只需要在HttpMethod method = new GetMethod("http://www.apa

服务器关闭连接

试验一 试验过程: 1.Server仅投递唯一一个AcceptEx接收请求. 2.Client连接. 3.Server于连接完成回调中以Client Socket作为线程参数创建子线程,线程函数是Func. 4.Func: 将调用closesocket(s)关闭连接,在这个过程中Client无退出无closesocket(s). Func关闭连接前 关闭后,Func退出前 Func退出后 小结: 前提:无数据传输,无待决IO,Client自始至终无退出无closesocket(s) 操作:Ser