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的区别。

最新文章

  1. sublime 配置jade高亮显示
  2. oracle建立数据库连接
  3. 接着上一篇 《Is WPF dead》
  4. 从零开始写redis客户端(deerlet-redis-client)之路——第一个纠结很久的问题,restore引发的血案
  5. PDO讲解
  6. 【转】C++中的虚函数的实现
  7. bat处理打开关门exe
  8. nginx的请求接收流程(一)
  9. BZOJ 1614: [Usaco2007 Jan]Telephone Lines架设电话线
  10. 20190402-display展现、float浮动
  11. SQL Server 创建跨库查詢、修改、增加、删除
  12. Django----博客文章数据返回
  13. Spring 使用介绍(十一)—— Spring事件
  14. Servlet解决中文乱码问题
  15. php中call_user_func 与 call_user_func_array的使用
  16. 使用skipper 扩展fabio 的路由&&http proxy 功能
  17. 浅析ARM公司在物联网领域的战略布局
  18. ny24 素数距离的问题 筛选法求素数
  19. MyEclipse 10 下在线安装插件
  20. spingboot集成jpa(二)

热门文章

  1. UWP开发小结
  2. Java调用Python遇到的一系列问题与解决方案
  3. 仿函数(functor)
  4. 栈 <stack> F - 宋飞正传
  5. HTML5按键打开摄像头和拍照
  6. [Bug]Python3.x AttributeError: libtest.so: undefined symbol: fact
  7. HDU-2050 折线分割平面 找规律&递推
  8. golang实现php里的serialize()和unserialize()序列和反序列方法
  9. JAVA JS 中的 modulus exponent 生成 C# 公匙
  10. hdu 4707 Pet【BFS求树的深度】