Как отправлять сообщения офлайн-пользователя после подключения к сети в веб-сокете Java?

Я пытаюсь написать чат с помощью webcocket, для пользователей в автономном режиме я использовал java Queue. Если пользователь находится в автономном режиме, я сохраняю сообщения в очереди, и когда пользователь подключается к сети, я проверяю, пуста ли очередь, а если нет, используя цикл, который я удаляю каждое сообщение из Queue. Проблема в том, что он просто отправляет последнее сообщение пользователю, хотя все сообщения находятся в очереди, вот мой метод onOpen:

@ServerEndpoint(value = "/chat/{room}/{user}", encoders = ChatMessageEncoder.class, decoders = ChatMessageDecoder.class)
 public class ChatEndpoint {


private final Logger log = Logger.getLogger(getClass().getName());
private static final Map<String, Queue<ChatMessage>> userMessageBuffer = new HashMap<>();

@OnOpen
public void open(final Session session,
        @PathParam("room") final String room,
        @PathParam("user") final String userId) {

    log.info("session openend and bound to room: " + room);
    // session.getUserProperties().put("room", room);
    session.getUserProperties().put("user", userId);

    Queue<ChatMessage> userMsgs = userMessageBuffer.get(userId);
    ChatMessage sendChat = new ChatMessage();

    if (userMsgs != null && !userMsgs.isEmpty()) {

        for (int i = 0; i < userMsgs.size(); i++) {

            sendChat = userMsgs.remove();
            System.out.println("size!!!!!! " + sendChat.getMessage());
            try {

                    session.getBasicRemote().sendObject(sendChat);

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (EncodeException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    }

}}

Кто-нибудь знает, где проблема?


person Nazila    schedule 07.07.2015    source источник
comment
Вы понимаете, что userMsgs.size() будет возвращать все меньшие и меньшие значения каждый раз, когда цикл for зацикливается?   -  person Kayaman    schedule 07.07.2015
comment
какой у вас брокер сообщений?   -  person Karthik    schedule 07.07.2015
comment
да с каждым разом все меньше   -  person Nazila    schedule 07.07.2015
comment
что такое брокер сообщений?   -  person Nazila    schedule 07.07.2015
comment
Если вам специально не нужен i для чего-то, просто используйте цикл while (userMsgs.size() > 0) вместо цикла for.   -  person JonK    schedule 07.07.2015
comment
Измените цикл for на for (ChatMessage sendChat : userMsgs), который намного чище и не использует избыточный целочисленный счетчик. Вам также не нужно беспокоиться о размере очереди.   -  person Tuxxy_Thang    schedule 07.07.2015
comment
Я сделал все это и все еще не работает, в случае использования, пока он ничего не отправляет   -  person Nazila    schedule 07.07.2015
comment
@nazila Можете ли вы опубликовать свой обновленный код отдельно в вопросе? Не изменяйте текущий код, а опубликуйте его в разделе «Редактировать» или «Обновить».   -  person Karthik    schedule 07.07.2015
comment
Я думаю, что проблема в открытом методе - это неподходящее место для отправки сообщения, но я не знаю, где это сделать.   -  person Nazila    schedule 07.07.2015
comment
@karthik Я заменил твой код своим циклом for,   -  person Nazila    schedule 07.07.2015
comment
@nazila, но ты сказал, что смог отправить последнее сообщение? Как это было отправлено? Я не думаю, что проблема в размещении onopen.   -  person Karthik    schedule 07.07.2015
comment
@nazila проблема не в твоем onOpen или send. Вы можете сделать так, что в этом нет ничего плохого. Проверьте здесь: tyrus.java.net/documentation/1.4/index /   -  person Karthik    schedule 07.07.2015
comment
проблема решена, я не знаю почему, но цикл while не работал, а for (ChatMessage sendChat: userMsgs) работал, @Tuxxy_Thang Спасибо   -  person Nazila    schedule 07.07.2015
comment
Рад, что решил. Причина будет заключаться в том, что он не делает то, что описал Картик, а именно то, что делал ваш код, и я подозреваю, что его предположение о том, что у вас было только 2 сообщения в очереди, поэтому вы отправили последнее сообщение тоже верно. По сути, мой цикл for начинается с головы и последовательно продолжается к хвосту, ничего не пропуская, пока очередь не будет исчерпана.   -  person Tuxxy_Thang    schedule 07.07.2015
comment
@Tuxxy_Thang, что вы подразумеваете под причина будет заключаться в том, что он не делает то, что описал Картик, а это то, что делал ваш код?   -  person Karthik    schedule 07.07.2015
comment
@karthik, лол, это был грубый способ согласиться с тем, что вы сказали об исходном коде OP, почему он, вероятно, отправлял только последнее сообщение. Я ненавижу эти маленькие поля для комментариев :D   -  person Tuxxy_Thang    schedule 07.07.2015


Ответы (1)


Полный код не проверял, но точно

      for (int i = 0; i < userMsgs.size(); i++)

это твоя проблема. Потому что вы используете i++ и проверяете userMsgs.size() как условие цикла for. Таким образом, вы увеличиваете i на 1 и уменьшаете размер userMsgs на 1, фактически вы сможете получить доступ только к половине элементов в очереди.

скажем, у вас изначально 8 элементов в очереди (представьте, что это похоже на Admiral General Aladeen, объясняющее ракету круглой формы)

               i=0 and userMsgs.size()=8
               i=1 and userMsgs.size()=7
               i=2 and userMsgs.size()=6
               i=3 and userMsgs.size()=5
               i=4 and userMsgs.size()=4 // comes out of loop.

вместо этого вы должны использовать цикл while,

  while(!userMsgs.isEmpty()){
   .....
  }

Вы сказали, что можете отправить пользователю только последнее сообщение, возможно, это потому, что у вас есть только 2 сообщения в очереди. Я знаю, что это редко, но это должно быть так в соответствии с вашим кодом.

person Karthik    schedule 07.07.2015