如何才能正确的关闭Socket连接

TCP协议角度来看,一个已建立的TCP连接有两种关闭方式,一种是正常关闭,即四次挥手关闭连接;还有一种则是异常关闭,我们通常称之为连接重置(RESET)。
首先说一下正常关闭时四次挥手的状态变迁,关闭连接的主动方状态变迁是FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT,而关闭连接的被动方的状态变迁是CLOSE_WAIT->LAST_ACK->TIME_WAIT。在四次挥手过程中ACK包都是协议栈自动完成的,而FIN包则必须由应用层通过closesocket或shutdown主动发送,通常连接正常关闭后,recv会得到返回值0,send会得到错误码10058。
除此之外,在我们的日常应用中,连接异常关闭的情况也很多。比如应用程序被强行关闭、本地网络突然中断(禁用网卡、网线拔出)、程序处理不当等都会导致连接重置,连接重置时将会产生RST包,同时网络络缓冲区中未接收(发送)的数据都将丢失。连接重置后,本方send或recv会得到错误码10053(closesocket时是10038),对方recv会得到错误码10054,send则得到错误码10053(closesocket时是10054)。
操作系统为我们提供了两个函数来关闭一个TCP连接,分别是closesocket和shutdown。通常情况下,closesocket会向对方发送一个FIN包,但是也有例外。比如有一个工作线程正在调用recv接收数据,此时外部调用closesocket,会导致连接重置,同时向对方发送一个RST包,这个RST包是由本方主动产生的。
shutdown可以用来关闭指定方向的连接,该函数接收两个参数,一个是套接字,另一个是关闭的方向,可用值为SD_SEND,SD_RECEIVE和SD_BOTH。方向取值为SD_SEND时,无论socket处于什么状态(recv阻塞,或空闲状态),都会向对方发送一个FIN包,注意这点与closesocket的区别。此时本方进入FIN_WAIT_2状态,对方进入CLOSE_WAIT状态,本方依然可以调用recv接收数据;方向取值为SD_RECEIVE时,双发连接状态没有改变,依然处于ESTABLISHED状态,本方依然可以send数据,但是,如果对方再调用send方法,连接会被立即重置,同时向对方发送一个RST包,这个RST包是被动产生的,这点注意与closesocket的区别。

时间: 2024-08-06 13:13:54

如何才能正确的关闭Socket连接的相关文章

HTTP协议学习笔记---HTTP持久连接和如何正确地关闭HTTP连接

一,持久连接 什么是持久连接?对于HTTP协议而言,它是基于请求响应模型,Client向Server发请求时,先建立一条HTTP连接,Server给Client响应数据后,连接关闭. 当Client发送下一个请求时,需要重新再建立HTTP连接,这种方式就是:一个请求响应需要占用一条HTTP连接.而持久连接就是:只需要建立一条连接,然后在这条连接上 传输多个请求和响应. 与持久连接相关的字段 HTTP1.0中有一个Connection首部字段,它是一个逐跳首部字段.Connection:Keep-

close与shutdown关闭socket连接的区别

close: int close(int fd) 并非马上关闭fd对应的socket连接,而是对其文件描述符的引用计数减1, 只有当fd的引用计数为0时,才关闭连接,对应fork复制的socket描述符, 无论时父进程还是子进程都需要调用close才能正确关闭连接. shutdown: int shutdown(int fd, int howto) 专为针对网络编程设计,一旦调用便终止socket连接, howto参数: 1.SHUT_RDWR (read & write) 同时关闭socket

C# Socket连接 无法访问已释放的对象

在进行Socket长连接时,若服务器或客户端出现异常时,另外一端对Socket对话进行操作时,程序会出现无法访问已释放的对象的问题.例如客户端出现问题主动断开Socket时,当服务器操作Socket时,比如主动断开Socket会话,那么程序会出现“无法方位已释放的对象”,是由于客户端的原因导致服务器和客户端的Socket已经不存在或连接已经断开,即Socket已经释放,服务器再操作服务器和客户端的Socket肯定会报错,因此在服务器或客户端一侧操作Socket时,必须首先判断Socket是否存在

高性能 TCP Socket连接关闭释放集中调度类

/// <summary> /// Socket关闭调度类,此类提供了静态访问,但是此类可以实例化 /// </summary> /// <remarks> /// Socket连接关闭类 /// 3个队列 /// 1.shotdown 关闭队列 /// 步骤1 /// 2.close 队列 间隔2秒 /// 步骤2 /// 3.dispose 队列 间隔1秒 /// 步骤3 /// </remarks> public class CloseSoketDis

Socket连接与HTTP连接

Socket连接与HTTP连接 我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用层协议,应用层协议有很多,比如HTTP.FTP.TELNET等,也可以自己定义应用层协议.WEB使用HTTP协议作应用层协议,以封装HTTP文本信息,然后使用TCP/IP做传输层协议将它发到网络上. 1)Socket是一个针对TCP和UDP编程的接口,你可以借助它建立TCP连接等等.而TCP和UDP协议属于传输层 .

Http和Socket连接区别

1.TCP连接 要想明白Socket连接,先要明白TCP连接.手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上. 建立起一个TCP连接需要经过“三次握手”: 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k

正确理解 SqlConnection 的连接池机制[转]

作者: eaglet 转载请注明出处 .net 中通过 SqlConnection 连接 sql server,我们会发现第一次连接时总是很耗时,但后面连接就很快,这个其实和SqlConnection 的连接池机制有关,正确的理解这个连接池机制,有助于我们编写高效的数据库应用程序. 很多人认为 SqlConnection 的连接是不耗时的,理由是循环执行 SqlConnection.Open 得到的平均时间几乎为0,但每次首次open 时,耗时又往往达到几个毫秒到几秒不等,这又是为什么呢? 首先

socket连接和TCP连接的关系

我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用层协议,应用层协议有很多,比如HTTP.FTP.TELNET等,也可以自己定义应用层协议.WEB使用HTTP协议作应用层协议,以封装HTTP文本信息,然后使用TCP/IP做传输层协议将它发到网络上. 1)Socket是一个针对TCP和UDP编程的接口,你可以借助它建立TCP连接等等.而TCP和UDP协议属于传输层 . 而http是个应用层的协议,它

netty 处理远程主机强制关闭一个连接

netty   处理远程主机强制关闭一个连接,首先看下api解释: /**  * Returns {@code true} if and only if the channel should not close itself when its remote  * peer shuts down output to make the connection half-closed.  If {@code false}, the connection  * is closed automaticall