我目前正在根据此示例开发一个简单的聊天多房间:

https://github.com/Atmosphere/atmosphere-samples/blob/master/samples/chat-multiroom/

我的开发环境:


Tomee Plus 1.7.2服务器
大气运行时版本2.4.0
Atmosphere-CDI版本2.4.0
Java EE 1.7
使用长轮询协议


在解释我的问题之前,这里我已经实现了聊天室的全局机制:


用户A连接到套接字“聊天/全部”。该插座允许
发送或接收他和他的对话者之间的任何通知。
用户A从第一个Web应用发出聊天请求并等待
(弹出式微调框)来自用户B的回复。
用户B也连接到套接字“聊天/全部”。用户B检查
每次从第二个Web应用程序发出的新聊天请求
(来自数据库的SQL请求)。如果他发现了新的请求,他可以或
不接受此请求。
用户B接受来自用户A的聊天请求。此刻,
套接字“聊天/全部”,用户B推送一条消息,表明他接受了
请求。之后,用户B连接到第二个插槽
“聊天/ 1”(特定聊天室的随机ID)。他现在在等
(类似于用户B的弹出式微调框)将用户A连接到同一用户
插座。
用户A收到此消息,并连接到套接字“聊天/ 1”。
现在,用户A已从服务器连接到此聊天室。
这个聊天室有两个用户,我向
仅用户B通知用户A已连接并关闭弹出窗口
微调器。


当我只广播一种资源的消息时,我没有问题。但是,当我为两个用户广播消息时,“ onMessage”方法被多次调用!

这是我关于管理聊天室的代码:

@ManagedService(path = "/chat/{id_room}")
public final class ChatRoom {

 //many static final private attribute

 private static final Logger logger = LoggerFactory.getLogger(Chat.class);

 @PathParam("id_room")
 private String idChatRoom;

 private final static String CHAT = "/chat/";

 private final HashMap<Integer, List<String>> users = new HashMap<Integer, List<String>>();

 private Universe universe;

 private BroadcasterFactory broadcasterFactory = Universe.broadcasterFactory();

 private AtmosphereResourceFactory resourceFactory = Universe.resourceFactory();

 private ChatMessageEncoderDecoder chatEncodeDecode = new ChatMessageEncoderDecoder();

@Message(encoders = { ChatMessageEncoderDecoder.class }, decoders = { ChatMessageEncoderDecoder.class })
 public final void onMessage(AtmosphereResource r, final ChatMessage message) throws UnsupportedEncodingException {
    Integer chatRoomId = !NOTIFICATION_SOCKET_ALL.equals(idChatRoom) == true ? Integer.parseInt(idChatRoom) : 0;
    [...]
    if(...) {
        [...]
    }
    else {
        roomsList.add(idChatRoom);
        boolean messageEmpty = "".equals(message.getMessage());
        boolean chatConnectedWithTwoUsers = users.get(chatRoomId).size() > 1;
        boolean chatConnectedWithOneUser = users.get(chatRoomId).size() == 1;
            if(chatConnectedWithTwoUsers && MESSAGE_EVENT.equals(message.getEvent())) { //communication between two users to the chat room id
                Users user = CDIUtil.getBean(RechercheUserService.class).getUserChat(message.getMail());
                if(user != null){
                    try {
                        List<String> listUsersFromRoom = users.get(chatRoomId);
                        message.setUsers(listUsersFromRoom);
                        message.setEvent(MESSAGE_EVENT);
                        logger.info("{} a envoyé le message {}", message.getAuthor(), message.getMessage());

                        String messageToSend = chatEncodeDecode.encode(message);
                        broadcasterFactory.lookup(CHAT + idChatRoom).broadcast(messageToSend);

                        String messageUtf8 = new String(message.getMessage().getBytes(), "UTF-8");
                        CDIUtil.getBean(MessageRoomsService.class).createMessageContents(idChatRoom, user, messageUtf8);
                    } catch (IMException e) {
                        message.setEvent(MESSAGE_NOT_REGISTER_EVENT);
                        logger.error("Impossible d'enregistrer le message de l'utilisateur");
                    }
                }
                else{
                    message.setEvent(USER_NOT_EXIST_EVENT);
                    logger.error("Utilisateur Inconnu");
                }
            }
            else if(chatConnectedWithOneUser) { //two users connected to the chat room id
                users.get(chatRoomId).add(r.uuid());
                logger.info("L'utilisateur {} a rejoint le chat {}", r.uuid(), idChatRoom);

                AtmosphereResource resource = resourceFactory.find(users.get(chatRoomId).get(0)); //get the first user connected to the chat room

                List<String> listUsersFromRoom = users.get(chatRoomId);
                message.setUsers(listUsersFromRoom);
                message.setEvent(CHAT_COMPLETE_EVENT);

                String messageToSend = chatEncodeDecode.encode(message);
                broadcasterFactory.lookup(CHAT + idChatRoom).broadcast(messageToSend, resource);
            }
        }
   }
}


因此,完成广播后,在界面用户上将显示3条消息。例如,用户A发送消息“您好,我能为您做什么?”,用户B看到此消息的3倍。

我认为有三个消息,因为两个套接字上有三个资源处于活动状态。实际上,第一个套接字“聊天/全部”对于一个资源(用户B)始终是活动的,第二个套接字“聊天/ 1”对于两个资源(用户A和用户B)都是活动的。有三种资源。

有没有人已经面临过这个问题?还是有人知道如何解决?

最佳答案

我也遇到了同样的问题..我已经解决了阅读此链接Multiple messages arrive as single response body or message received are incomplete的问题:

我已在Atmosphere Servlet中将此init-param添加到web.xml中

<init-param>
   <param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
   <param-value>org.atmosphere.client.TrackMessageSizeInterceptor</param-value>
</init-param>


在客户端,我在请求中添加了trackMessageLength : true

var request = { url: document.location.toString() + 'chat',
                contentType : "application/json",
                logLevel : 'debug',
                transport : 'long-polling' ,
                trackMessageLength : true,
                fallbackTransport: 'long-polling'};


正如在此链接中报告的


  如果广播多条消息,并且基础服务器将它们缓冲在内存中,则可以用多条消息而不是一条消息来调用atmopshere.js回调或函数。如果使用文本,则可能不是问题,但如果使用JSON,则解析可能会失败,因为您的回调/函数会被多个JSON消息调用。


希望这也对您有用!

09-10 07:30
查看更多