如何才能正确的关闭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-02 20:13:57

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

socket连接和http连接的区别

相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助. 首先一定要明白: HTTP协议:简单对象访问协议,对应于应用层  ,HTTP协议是基于TCP连接的 tcp协议:    对应于传输层 ip协议:     对应于网络层  TCP/IP是传输层协议,主要解决数据如何在网络中传输:而HTTP是应用层协议,主要解决如何包装数据. Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过S

socket连接,偶尔发生这个异常,是什么原因引起的?

问题描述 socket连接,偶尔发生这个异常,是什么原因引起的? java.net.SocketException: Connection reset at java.net.SocketInputStream.read(SocketInputStream.java:196) at java.net.SocketInputStream.read(SocketInputStream.java:122) at java.net.SocketInputStream.read(SocketInputSt

c# 如何判断socket连接断开?

问题描述 privatevoidtimer1_Tick(objectsender,EventArgse){if(socket!=null&&socket.Connected){if(socket.Poll(1,SelectMode.SelectRead)){try{byte[]temp=newbyte[1024];intnRead=socket.Receive(temp);if(nRead==0){MessageBox.Show("000连接已断开了,请处理");}}c

muduo 的 shutdown()没有直接关闭 TCP连接的原因

今天收到一位网友来信: 在 simple 中的 daytime 示例中,服务端主动关闭时调用的是如 下函数序列,这不是只是关闭了连接上的写操作吗,怎么是关闭了整个连接? 1: void DaytimeServer::onConnection(const muduo::net::TcpConnectionPtr& conn) 2: { 3:   if (conn->connected()) 4:   { 5:     conn->send(Timestamp::now().toForma

并发请求限制-为什么CAsyncSocket的最大连接数只能达到两百多个,得怎么弄才能接收超过1000个连接?

问题描述 为什么CAsyncSocket的最大连接数只能达到两百多个,得怎么弄才能接收超过1000个连接? 我在做TCP的服务器,用的是CAsyncSocket,使用默认的serverSocket.listen()时,用jmeter做测试, 只有6个链接正常接收.返回数据正确,其他并发请求返回都为Connection refused. 使用serverSocket.listen(1024)时,jmeter并发请求300个,正确返回的线程数从300个不断下降, 最后稳定在206个.从jmeter的

安卓源码-安卓代码无法socket连接个人笔记本服务器~一直没能解决这个问题,求帮助

问题描述 安卓代码无法socket连接个人笔记本服务器~一直没能解决这个问题,求帮助 服务器代码: import java.awt.FlowLayout; import java.awt.Frame; import java.awt.TextArea; import java.awt.TextField; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedR

socket-安卓 Socket通信,Socket连接不上,程序就在真机崩溃但在模拟器上正常

问题描述 安卓 Socket通信,Socket连接不上,程序就在真机崩溃但在模拟器上正常 class ReceiveData extends Thread { int i=1; private void reconnect( ) { Log.i("第"+i+"次连接","reconnect刚开始执行"); try { Log.i("第"+i+"次连接","Socket之前"); Sock

服务器-C#Socket连接,第一次要很久

问题描述 C#Socket连接,第一次要很久 各位,我写了个 Socket 程序,服务端总是开启着,客户端偶尔连接.偶尔断开.现在如果客户端断开很久后再去连服务器,第一次要很久才能连接成功.大家有没有碰到这种情况? 麻烦各位大侠多指点. 解决方案 我也遇到了这样的问题,该如何解决

通信-android 客户端socket连接服务器,socket何时close

问题描述 android 客户端socket连接服务器,socket何时close 假设socket连接好了,现在客户端向服务器发送完了数据,这个时候需要关闭socket吗?如果关闭后,某个时候又需要发送其他数据,再建立连接? 还是说建立通信协议,一次socket连接后一直保持通信状态,根据通信协议对不同的数据进行不同的处理,然后等客户端程序退出时再关闭socket. 解决方案 Android客户端通过Socket连接服务器Android客户端与java服务器端的Socket连接Socket服务