发送消息后,套接字神秘地从哈希图中删除

Posted

技术标签:

【中文标题】发送消息后,套接字神秘地从哈希图中删除【英文标题】:Socket gets mysteriously removed from hashmap after sending a message 【发布时间】:2021-04-19 07:21:16 【问题描述】:

所以我是 Java 套接字的新手,刚刚开始使用它们。问题是:我有一个客户端和一个服务器应用程序。客户端想要向另一个客户端发送一些消息。这些消息将到达服务器,并在服务器端将它们放入队列中,并每 2 秒检查一次目标客户端(套接字)是否还活着。如果是这样,那么我将清空队列并将每条消息发送给特定的客户端。否则,消息将存储在服务器应用程序中,直到目标套接字处于活动状态。

但是,主要问题是在服务器将第一条消息传递到套接字后,客户端(目标)套接字消失了。我尝试将这些套接字存储在哈希图中。因此,在发送了第一条消息后,哈希映射会以某种方式变空。而且我无法传递其余的消息。

我提供一些代码:

public class Server 
    
    public static volatile HashMap<Socket,String> clients;
    
    public Server()
        clients = new HashMap<>();
    
    
    
    
    public void start()
        try(ServerSocket serverSocket = new ServerSocket(5000))
            
            while(true)
            
                
                Socket socket = serverSocket.accept();
                System.out.println("Client connected");
                
                new clientHandler(socket).start();
                
            
 
        
        catch(IOException e)
            e.printStackTrace();
        
            
    
    

public class clientHandler extends Thread
    
    private Socket socket;
    private Socket sendSocket;
    private Timer timer;
    private Queue<String> msgStack;
    private String socketName = "";
    
    
    public clientHandler(Socket socket)
        this.socket = socket;
        msgStack = new PriorityQueue<>();
    
    
    
    
    @Override
    public void run()
        try 
            BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            
            PrintWriter output = new PrintWriter(socket.getOutputStream(),true);
            
            while(true)
            
                String line = input.readLine();
               if(!line.contains("|") && line != null)
                    if(!isClientAdded(line))
                        
                        Server.clients.put(socket, line);
                    
                else
                    
                    System.out.println(line);
                    String[] msg = line.split("\\|");
                    
                    String fromUser = msg[0];
                    String toUser = msg[1];
                    String subject = msg[2];
                    String msgText = msg[3];
                    
                    if(isClientAdded(toUser))
                        sendMsg(line);
                        if(timer.isRunning())
                            timer.stop();
                        
                    else
                        msgStack.add(line);
                        timer = new Timer(2000, new ActionListener() 
                            @Override
                            public void actionPerformed(ActionEvent e) 
                                System.out.println(msgStack+" "+msgStack.size());
                                if(isClientAdded(toUser))
                                    if(!msgStack.isEmpty())
                                        sendMsg(msgStack.poll());
                                        System.out.println("MSg: "+fromUser+" "+toUser+" "+subject+" "+msgText);
                                    
                                    if(msgStack.isEmpty())
                                        timer.stop();
                                    
                                
                            
                        );
                        
                        timer.start();
                    
                
            
            
         catch (SocketException ex) 
            ex.printStackTrace();
            Server.clients.remove(socket);
         catch (IOException ex) 
            ex.printStackTrace();
        
    
    
    public boolean isClientAdded(String clientName)
        
        Iterator it = Server.clients.entrySet().iterator();
                        while (it.hasNext()) 
                            Map.Entry pair = (Map.Entry)it.next();
                            if(clientName.equals(pair.getValue()+""))
                                return true;
                            
                            it.remove(); 
                    
        return false;
    
    
    public void sendMsg(String send)
        
        String[] msg = send.split("\\|");
                    
        String fromUser = msg[0];
        String toUser = msg[1];
        String subject = msg[2];
        String msgText = msg[3];
        
        Iterator it = Server.clients.entrySet().iterator();
            while (it.hasNext()) 
                Map.Entry pair = (Map.Entry)it.next();
                if((pair.getValue()+"").equals(toUser))
                    
                    try 
                        socket = ((Socket)pair.getKey());
                        PrintWriter output = new PrintWriter(socket.getOutputStream(),true);
                        output.println(fromUser+"|"+subject+"|"+msg);
                     catch (IOException ex) 
                        ex.printStackTrace();
                    
                
                 
             it.remove(); 
        
    
    

我从其对“名称”中识别出每个套接字。这就是我如何知道我应该发送消息的套接字。

【问题讨论】:

你在 isClientAdded 的 hashmap 中明确删除了条目,为什么? 【参考方案1】:

是的,我遇到了问题,感谢评论部分中的 Rocco。问题是 it.remove() 部分。我从另一个项目复制/粘贴了这个 hashmap 迭代代码,因为在我的记忆中这个 hashmap 迭代器只是简单的迭代,但它最后有一个 it.remove(),我不记得了。

【讨论】:

以上是关于发送消息后,套接字神秘地从哈希图中删除的主要内容,如果未能解决你的问题,请参考以下文章

发送消息保证后,是否与TCP套接字断开连接?

发送几条消息后,WebSocket readyState 停留在 0

用户的套接字与服务器断开连接后如何发送消息

如何使用Faye Websockets向特定客户端发送消息?

Python Socket - 同时发送/接收消息

Discord bot 发送后删除消息