文章目录
- 三种方法效果的区别
- 套接字Socket关闭与释放的区别
- 服务器执行三种关闭操作后,继续发送/接收数据会发生什么
- `socket.shutdownOutput` 关闭连接
找了半个小时没一个说明白的帖子,真的折磨
三种方法效果的区别
socket.close()
Socket主动禁止输入和输出流,关闭Socket并丢弃所有的缓冲区未发送数据,发送FIN四次分手,等待关闭连接,释放Socket、输入输出流资源output/input.close()
只关闭本机上的输入/输出流,影响的是程序<--->接口
这一段。Socket不会禁止输入/输出流操作,它不知道自己的输入/输出流已经关闭了。这是程序内部问题,双方Socket行为还是保持原样,但是会因为到达的数据没法交付给程序导致报错甚至崩溃socket.shutdownOutput/Input()
Socket主动禁止输入/输出流,发送FIN四次分手,等待关闭连接,释放Socket、输入/输出流等资源
综上,socket.close()
方法关闭整个Socket连接,禁止输入和输出操作,并且最终关闭连接和释放资源。output.close()
方法关闭输出流,禁止进一步的写操作,具体的影响取决于实现和是否与Socket关联。socket.shutdownOutput()
方法关闭Socket的输出流,禁止写操作,但允许继续使用输入流,发送FIN包通知对方关闭连接,并以四次握手过程完成连接关闭。
套接字Socket关闭与释放的区别
-
套接字的关闭(Socket Close):
关闭套接字是指在网络通信结束或不再需要使用套接字时,显式地关闭套接字连接。通过调用套接字对象的close()
方法,可以关闭套接字。关闭套接字后,不再能够进行数据传输,连接也被终止。关闭套接字是网络编程中常用的操作,用于释放与远程主机的连接以及清理资源。 -
套接字资源的释放(Socket Resource Release):
套接字资源的释放是指在关闭套接字后,操作系统或编程语言运行环境会自动回收与套接字相关的资源。这些资源包括分配给套接字的内存空间、操作系统中的套接字句柄、网络协议栈中的缓冲区等。套接字资源的释放由操作系统或运行环境负责处理,通常会在套接字关闭后的一段时间内完成。
总结来说,关闭套接字是由程序显式调用的操作,用于结束连接并停止数据传输。而套接字资源的释放是随后由操作系统或运行环境自动进行的过程,用于回收之前使用的资源。关闭套接字是触发套接字资源释放的条件之一。
服务器执行三种关闭操作后,继续发送/接收数据会发生什么
当服务器执行 socket.close()
、output.close()
或 socket.shutdownOutput()
操作后,如果客户端试图向服务器发送数据,将会发生以下情况:
-
服务器执行
socket.close()
后:- 服务器Socket被关闭,无法接收客户端发送的数据。
- 客户端的发送操作将失败,并且可能引发异常(如连接错误或连接重置RST)。 在网络层面,当客户端尝试发送数据时,其操作系统会报错连接已关闭。
-
服务器执行
output.close()
后:- 客户端可以成功发送数据到服务器,并且服务器仍然可以通过输入流接收来自客户端的数据。只是服务器无法通过输出流向客户端发送任何数据(报错输出流已释放)。
-
服务器执行
socket.shutdownOutput()
后:- Socket的输入端仍然是打开状态,而输出端被关闭。这意味着Socket可以继续接收来自对方的数据,但无法再向对方发送数据。
-
服务器执行
input.close()
后:- 客户端可以成功发送数据到服务器,但服务器没法接收数据了,因为输入流已经释放掉了,数据会卡在Socket那步
-
服务器执行
socket.shutdownInput()
后:- 客户端会收到服务器发来的FIN,就不会给服务器发数据了。如果非要发,就会引发异常和错误
socket.shutdownOutput
关闭连接
此种TCP四次分手过程:
- 服务器
socket.shutdownOutput
向客户端发送第一个FIN,并关闭输出流。 - 客户端接收到服务器的FIN后,发送一个ACK确认收到,并进入TIME_WAIT状态。
- 客户端发送第二个FIN,并关闭输出流。
- 服务器接收到客户端的FIN后,发送一个ACK确认收到,并关闭Socket。
- 客户端在收到服务器的ACK后,会等待一段时间(2MSL),确保服务器收到了自己刚刚发的正确地ACK并关闭Socket。这段时间被称为2MSL(两倍最大报文生存时间)
ps.在TCP协议中,FIN和ACK报文是用来控制连接状态的特殊报文,它们不受Socket输出流的影响。当服务器调用 socket.shutdownOutput() 方法后,它会关闭自己的输出流,但仍然可以发送ACK报文来响应客户端的FIN报文。