Java:如何使用ServerSocket和Socket正确关闭套接字连接

3
我目前有一个简单的即时通讯程序,它使用Java的SocketServerSocket类。它正在按预期运行,但是当我尝试关闭连接时,它没有使用四次握手TCP拆除来关闭连接。相反,它使用RST数据包突然关闭连接。
我关闭连接的方式是从客户端向服务器发送一个字符串,服务器将识别为关闭连接的命令。然后我在服务器上使用ServerSocket.close()方法,在客户端上使用Socket.close()方法。
使用这些类正确关闭TCP连接的正确方式和/或事件顺序是什么?
客户端断开连接代码:
//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拆除过程是包括四次握手。向远程主机发送一个FIN数据包,然后从远程主机返回一个ACK数据包。然后从远程主机发送一个FIN数据包,然后向远程主机发送一个ACK数据包。当通过Wireshark监视流量时,我没有得到这个。相反,我收到了一个FIN数据包到远程服务器,然后从服务器返回一个RST/ACK。
这个image展示了一个正确的TCP四次挥手过程。
到目前为止,我所发现的所有内容都表明,只需调用close()或让Java的Try-with-resources语句处理清理即可。我无法想象Java会实现与标准TCP规范不符的功能。虽然很有可能我会以错误的顺序调用某些行,或者类似的情况,但我并不知情。
2个回答

3

如果您在关闭时重置自己的连接,则可能是以下两种情况之一:

  1. 您尚未读取对等方发送的所有挂起传入数据,或
  2. 您已向先前已被对等方关闭的连接写入。

在这两种情况下,都会出现应用程序协议错误。


我怀疑我还没有读取所有由对方发送的待处理传入数据,因为我立即将发送到屏幕上的内容显示在服务器端。你能提供一种检查这种情况的方法吗?我想我在那里有逻辑来检查连接是否仍然打开,但我会再次确认。谢谢你的建议。 - d.lanza38
我通过从客户端代码中删除this.clientRemoteSocket.close();这一行来修复了这个问题。发生的情况是套接字被客户端或服务器(无论哪一个先到达该行)关闭,然后尝试使用另一行再次关闭套接字。我怀疑也可以通过从服务器端代码中删除serverLocalSocket.close();这一行,并保留另一行来进行修正。 - d.lanza38
双方都需要关闭连接的一端,即他们的套接字,但是双方都需要先读取所有已发送的内容。 - user207421

1
TCP的一个很棒的特点是,如果你关闭了套接字,你的伙伴会自动知道并在读取时抛出错误。
所以在客户端,你只需要做以下操作:
clientRemoteSocket.close();

只需在正常数据读取过程中添加一个错误情况即可解决此问题。
try {
    // Read from the socket:
    incoming = socketInputStream.read();

    // Handle the data here

} catch (IOException e) {
    // Client has disconnected
}

可能有一个更具体的异常你可以捕获,我不确定,已经有一段时间了。但是应该可以工作。祝你好运!

那么Connection reset by peer错误是什么意思呢?难道不是在远程套接字关闭时发生的吗? - Anubian Noob
只有在做得不正确的情况下才会看到我的答案。你提供的内容并没有解决问题。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接