Java: 如何使用 ServerSocket 和 Socket 正确关闭套接字连接
Java: How to properly close a socket connection using ServerSocket and Socket
我目前有一个简单的即时消息程序,它利用了 Java 的 Socket and ServerSocket 类。它按预期运行,但是当我尝试关闭连接时,它没有使用 4 次握手 TCP 拆卸来关闭连接。相反,它使用 RST 数据包突然关闭连接。
我关闭连接的方式是从客户端向服务器发送一个字符串,服务器会将其识别为关闭连接的命令。然后,我在服务器上使用 ServerSocket.close()
方法,在客户端上使用 Socket.close()
方法。
使用这些 类 正确关闭 TCP 连接的正确方法 and/or 事件顺序是什么?
客户端断开代码:
//Disconnects from remote server
//Returns true on success, false on failure
public boolean disconnect(){
try{
this.clientOut.println("0x000000");
this.clientRemoteSocket.close();
this.isConnected = false;
return true;
}catch(Exception e){
return false;
}
}
服务器端断开代码:
//Check to see if the client wants to close the connection
//If yes, then close the connection and break out of the while loop
if(incoming.equals("0x000000")){
serverLocalSocket.close();
break;
}
编辑:
代码工作得很好。我只是想在 Java 中学习套接字编程,并且知道正确的 TCP 拆卸过程是包括 4 次握手。一个 FIN 数据包到远程主机,然后一个 ACK 数据包从远程主机返回。然后是来自远程主机的 FIN 数据包,然后是到远程主机的 ACK 数据包。通过 Wireshark 监控流量时,我没有得到。相反,我正在获取远程服务器的 FIN,然后从服务器返回 RST/ACK。
此 image 描述了正确的 TCP 4 路拆卸过程。
到目前为止,我发现的所有内容都表明,所有需要的只是调用 close() 或让 Java 的 Try-with-resources 语句处理清理。我看不到 Java 实现了不符合标准 TCP 规范的功能。很有可能我以错误的顺序或类似的方式调用了某些行,我只是没有意识到。
关于 TCP 的重要部分是,如果您关闭套接字,您的合作伙伴会自动知道并在读取时抛出错误。
所以您在客户端中要做的就是:
clientRemoteSocket.close();
对于服务器,只需在正常读取数据时添加一个错误案例即可:
try {
// Read from the socket:
incoming = socketInputStream.read();
// Handle the data here
} catch (IOException e) {
// Client has disconnected
}
您可能会发现一个更具体的异常,我不确定,已经有一段时间了。但这应该有效。祝你好运!
如果您在关闭时重置自己的连接,可以:
- 您尚未读取对等方发送的所有待处理传入数据,或者
- 您已经写入了之前已被对方关闭的连接。
在这两种情况下,应用程序协议错误。
我目前有一个简单的即时消息程序,它利用了 Java 的 Socket and ServerSocket 类。它按预期运行,但是当我尝试关闭连接时,它没有使用 4 次握手 TCP 拆卸来关闭连接。相反,它使用 RST 数据包突然关闭连接。
我关闭连接的方式是从客户端向服务器发送一个字符串,服务器会将其识别为关闭连接的命令。然后,我在服务器上使用 ServerSocket.close()
方法,在客户端上使用 Socket.close()
方法。
使用这些 类 正确关闭 TCP 连接的正确方法 and/or 事件顺序是什么?
客户端断开代码:
//Disconnects from remote server
//Returns true on success, false on failure
public boolean disconnect(){
try{
this.clientOut.println("0x000000");
this.clientRemoteSocket.close();
this.isConnected = false;
return true;
}catch(Exception e){
return false;
}
}
服务器端断开代码:
//Check to see if the client wants to close the connection
//If yes, then close the connection and break out of the while loop
if(incoming.equals("0x000000")){
serverLocalSocket.close();
break;
}
编辑: 代码工作得很好。我只是想在 Java 中学习套接字编程,并且知道正确的 TCP 拆卸过程是包括 4 次握手。一个 FIN 数据包到远程主机,然后一个 ACK 数据包从远程主机返回。然后是来自远程主机的 FIN 数据包,然后是到远程主机的 ACK 数据包。通过 Wireshark 监控流量时,我没有得到。相反,我正在获取远程服务器的 FIN,然后从服务器返回 RST/ACK。
此 image 描述了正确的 TCP 4 路拆卸过程。
到目前为止,我发现的所有内容都表明,所有需要的只是调用 close() 或让 Java 的 Try-with-resources 语句处理清理。我看不到 Java 实现了不符合标准 TCP 规范的功能。很有可能我以错误的顺序或类似的方式调用了某些行,我只是没有意识到。
关于 TCP 的重要部分是,如果您关闭套接字,您的合作伙伴会自动知道并在读取时抛出错误。
所以您在客户端中要做的就是:
clientRemoteSocket.close();
对于服务器,只需在正常读取数据时添加一个错误案例即可:
try {
// Read from the socket:
incoming = socketInputStream.read();
// Handle the data here
} catch (IOException e) {
// Client has disconnected
}
您可能会发现一个更具体的异常,我不确定,已经有一段时间了。但这应该有效。祝你好运!
如果您在关闭时重置自己的连接,可以:
- 您尚未读取对等方发送的所有待处理传入数据,或者
- 您已经写入了之前已被对方关闭的连接。
在这两种情况下,应用程序协议错误。