我目前正在根据这个例子开发一个简单的聊天多房间:
https://github.com/Atmosphere/atmosphere-samples/blob/master/samples/chat-multiroom/
我的开发环境:
在解释我的问题之前,我已经实现了聊天室的全局机制:
用户A连接到套接字" chat / all"。这个插座允许 发送ou接收他和他的对话者之间的任何通知。
用户A从第一个网络应用程序发出聊天请求并等待 (弹出式微调器)来自用户B的响应。
用户B也连接到套接字" chat / all"。用户B检查 每次,从第二个Web应用程序,如果有新的聊天请求 (来自数据库的SQL请求)。如果他找到了新的请求,他可以或 不接受这个要求。
用户B接受来自用户A的聊天请求。此时,通过 socket" chat / all",用户B按下一条消息表示他已接受此消息 请求。之后,用户B连接到第二个插座 "聊天/ 1" (特定聊天室的随机ID)。他现在在等 (用户B之类的弹出式微调器)用于连接到用户A的用户A. 插座。
用户A收到此消息并连接到套接字" chat / 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发送消息&#34;您好,我能为您做什么?&#34;,用户B看到此消息的3次。
我认为有三条消息,因为两个套接字上有三个资源处于活动状态。的确,第一个插座&#34;聊天/全部&#34;对于一个资源(用户B)和第二个套接字&#34; chat / 1&#34;对两个资源(用户A和用户B)有效。有三种资源。
有没有人已经面临这个问题?或者是否有人知道如何解决它?
答案 0 :(得分:0)
我也有同样的问题..我已经解决了阅读此链接的问题Multiple messages arrive as single response body or message received are incomplete:
我在我的Atmosphere Servlet中添加了web.xml这个init-param
<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消息调用。
我希望这也适合你!