【问题标题】:Java Socket: Check if Client socket is disconnectedJava Socket:检查客户端套接字是否断开连接
【发布时间】:2018-04-20 18:37:55
【问题描述】:

我有一个线程等待客户端发送请求。这个线程是一个while循环,一旦它从客户端接收到一个ObjectDataStream,它就会向客户端发送一个OutputDataStream。这一切都很好,而且效果很好。

我有另一个线程来处理检查客户端套接字是否断开连接。我这样做的方式是:

  • 将所有连接的客户端放入一个数据结构中
  • 循环访问此数据结构中的每个套接字
  • 向此套接字发送 DataOutputStream
  • 检查 DataOutputStream 是否工作。如果确实如此 => 客户端仍处于连接状态。如果它不起作用,客户端断开连接 => 从数据结构中删除客户端并重新开始循环

现在我面临的主要问题是处理断开连接的套接字的线程正在中断服务器和客户端之间的 DataStreams。

客户端代码:它发送一个请求对象并等待来自服务器的布尔响应。

outToServer.writeObject(request);
boolean loggedIn = inFromServer.readBoolean();
return loggedIn;

服务器代码:检查用户名和密码是否有效并基于它返回一个布尔值。然后它将这个布尔值发送给客户端。

boolean loggedIn = Server.loginUser(username, password, clientSocket);
outToClient.writeBoolean(loggedIn);

处理断开连接的客户端的线程:

在线客户: public static Map<Socket, User> onlineClients

while (true) {
    for (Iterator<Socket> iter = onlineClients.keySet().iterator(); iter.hasNext();) {
        Socket client = iter.next();
        try {
            DataOutputStream outToClient = new DataOutputStream(client.getOutputStream());
            outToClient.writeUTF("Client you there?");
        } catch (IOException e) {
            System.out.println("Removing client: " + client.getPort());
            iter.remove();
            System.out.println("There are : " + onlineClients.size() + " online clients");
        }
    }
}

当上述线程运行时,它会中断boolean loggedIn = inFromServer.readBoolean(); 部分代码,其中loggedIn 应该为真,但它变为假。我知道这一点,因为如果我注释掉该线程,loggedIn 将变为 true。所以我想也许outToClient.writeUTF("Client you there?"); 打断了它。

我的代码太长了,我尽量总结一下。

【问题讨论】:

    标签: java serversocket


    【解决方案1】:

    在没有正确同步的情况下,永远不要从两个线程写入流!

    方法是将所有将数据写入流的部分包装到同步块中:

    synchronized(client) {
        DataOutputStream outToClient = new DataOutputStream(client.getOutputStream());
        outToClient.writeUTF("Client you there?");
    }
    
    
    synchronized(clientSocket) {
        boolean loggedIn = Server.loginUser(username, password, clientSocket);
        outToClient.writeBoolean(loggedIn);
    }
    

    如果两个部分在同一个对象上同步,那么您是安全的,因为只有一个线程可以在同步块内执行。

    【讨论】:

    • 是的,但这不会阻止outToClient.writeUTF("Client you there?"); 被发送并影响boolean loggedIn = inFromServer.readBoolean();
    • 我发现了一个小但可能无效的解决方案,即在Thread.sleep(2000) 之前使用outToClient.writeUTF("Client you there?");
    猜你喜欢
    • 2010-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多