无法使用 Atmosphere 运行时广播到单个连接

发布于 2024-10-09 09:16:45 字数 1619 浏览 4 评论 0原文

我正在使用 Atmosphere 运行时 0.6 快照。 Tomcat 7 正确记录我正在使用 Http11 Nio 连接器,并且没有任何关于将使用 BlockingIO 的警告。

我正在尝试将消息发送到三种渠道。

  1. Global Broadcaster - 向所有暂停的资源广播。 (全部)
  2. 广播到特定资源(例如,合作伙伴)
  3. 广播到当前资源(自己)

当发生登录操作时,我必须在会话中存储什么才能实现这种广播?

我的代码的一些细节如下:

  1. 我的处理程序实现 AtmosphereHandler
  2. 在构造函数中,我实例化了 globalBroadcaster,如下所示:

    globalBroadcaster = new DefaultBroadcaster();

  3. On登录,

    resource.getAtmosphereConfig().getServletContext().setAttribute(name, selfBroadcaster); 其中 name 是请求参数中的用户名,selfBroadcaster 是 DefaultBroadcaster 的新实例。

  4. 这是 sendMessageToPartner 的代码,

私有同步无效 sendMessageToPartner(广播者 selfBroadcaster, AtmosphereResource资源、字符串名称、字符串消息){
// 这给出了合作伙伴的名字
String Partner= (String) resource.getAtmosphereConfig().getServletContext().getAttribute(name + PARTNER_NAME_TOKEN);
// 获取合作伙伴的广播公司
广播者outsiderBroadcaster =(广播者)资源
.getAtmosphereConfig().getServletContext()
.getAttribute(合作伙伴);
if (outsiderBroadcaster == null) {
sendMessage(selfBroadcaster, "无效用户" + 合作伙伴);
返回;
}
// 广播给合作伙伴
externalrBroadcaster.broadcast(" **" + message);

我希望我已经提供了所有必需的信息。如果需要,我可以提供更多信息。

问题是,全局消息被发送。当向合作伙伴发送消息时,有时会被阻止,客户端根本不会收到该消息。在 3-4 条消息后,这种情况会持续发生。

是否存在一些线程问题?我做错了什么?

我希望有人能帮我解决这个问题。

I am using Atmosphere runtime 0.6 Snapshot. Tomcat 7 is logging correctly that I am using the Http11 Nio connector and there is no warning that BlockingIO will be used.

I am trying to send messages to three kinds of channels.

  1. Global Broadcaster - broadcast to all suspended resources. (All)
  2. Broadcast to a particular resource (say, Partner)
  3. Broadcast to current resource (Self)

When a login action occurs, what all do I have to store in session in order to achieve this kind of broadcasting?

Some details of my code are as follows:

  1. My Handler implements AtmosphereHandler
  2. In the constructor, I instantiate the globalBroadcaster as follows:

    globalBroadcaster = new DefaultBroadcaster();

  3. On login,

    resource.getAtmosphereConfig().getServletContext().setAttribute(name, selfBroadcaster);
    where name is the user name from request parameter and selfBroadcaster is a new instance of DefaultBroadcaster.

  4. Here is the code for sendMessageToPartner,


private synchronized void sendMessageToPartner(Broadcaster selfBroadcaster,
AtmosphereResource<HttpServletRequest, HttpServletResponse> resource,String name, String message) {
// this gives the partner's name
String partner= (String) resource.getAtmosphereConfig().getServletContext().getAttribute(name + PARTNER_NAME_TOKEN);
// get partner's broadcaster
Broadcaster outsiderBroadcaster = (Broadcaster) resource
.getAtmosphereConfig().getServletContext()
.getAttribute(partner);
if (outsiderBroadcaster == null) {
sendMessage(selfBroadcaster, "Invalid user " + partner);
return;
}
// broadcast to partner
outsiderBroadcaster.broadcast(" **" + message);

I hope I have given all the required information. I can provide more information if required.

The problem is, the global message gets sent. When message to partner is sent, sometimes it gets blocked, the message is not received in the client at all. This happens consistently after 3-4 messages.

Is there some threading problem? What am I doing wrong?

I hope somebody helps me out with this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

戈亓 2024-10-16 09:16:45

好的,我弄清楚了如何使用 Atmosphere 运行时来实现这一点。
首先,我升级到 0.7 SNAPSHOT,但我认为相同的逻辑也适用于 0.6。

因此,要为单个用户创建广播器:

在 GET 请求中,

  // Use one Broadcaster per AtmosphereResource             
try {       
atmoResource.setBroadcaster(BroadcasterFactory.getDefault().get());     

} catch (Throwable t) {
                throw new IOException(t);
            }

            // Create a Broadcaster based on this session id.
            selfBroadcaster = atmoResource.getBroadcaster();
            // add to the selfBroadcaster
            selfBroadcaster.addAtmosphereResource(atmoResource);

            atmoResource.suspend();   

调用登录操作时,

//Get this broadcaster from session and add it to BroadcasterFactory.

Broadcaster selfBroadcaster = (Broadcaster) session.getAttribute(sessionId);

BroadcasterFactory.getDefault().add(selfBroadcaster, name);

Now the global broadcaster. The logic here is, you create a broadcaster from the first resource and then add each resource as they log in.

Broadcaster globalBroadcaster;

globalBroadcaster = BroadcasterFactory.getDefault().lookup(DefaultBroadcaster.class, GLOBAL_TOKEN, false);
                if (globalBroadcaster == null) {
                  globalBroadcaster = selfBroadcaster;

                    } else {
                        BroadcasterFactory.getDefault().remove(
                                globalBroadcaster, GLOBAL_TOKEN);
                        AtmosphereResource r = (AtmosphereResource) session
                                .getAttribute("atmoResource");
                        globalBroadcaster.addAtmosphereResource(r);

                    }
                    BroadcasterFactory.getDefault().add(globalBroadcaster,
                            GLOBAL_TOKEN);

最后,您可以广播到单个连接或全局到所有连接,如下所示:

// Single Connection/Session
Broadcaster singleBroadcaster= BroadcasterFactory.getDefault().lookup(
                            DefaultBroadcaster.class, name);
singleBroadcaster.broadcast("Only for you");

// Global 
Broadcaster globalBroadcaster = BroadcasterFactory.getDefault().lookup(DefaultBroadcaster.class,GLOBAL_TOKEN, false);
globalBroadcaster.broadcast("Global message to all");

要向合作伙伴发送消息,只需查找合作伙伴的广播器并对单连接执行与上述相同的操作。

希望这可以帮助那些试图实现同样目标的人。
可能有更好的方法来做到这一点。
我想我将不得不使用这种方法,直到有人提出更好的解决方案。

Ok, I figured out how this can be achieved with Atmosphere runtime.
First, I upgraded to 0.7 SNAPSHOT, but I think the same logic would work with 0.6 as well.

So, to create a broadcaster for a single user:

In GET request,

  // Use one Broadcaster per AtmosphereResource             
try {       
atmoResource.setBroadcaster(BroadcasterFactory.getDefault().get());     

} catch (Throwable t) {
                throw new IOException(t);
            }

            // Create a Broadcaster based on this session id.
            selfBroadcaster = atmoResource.getBroadcaster();
            // add to the selfBroadcaster
            selfBroadcaster.addAtmosphereResource(atmoResource);

            atmoResource.suspend();   

When login action is invoked,

//Get this broadcaster from session and add it to BroadcasterFactory.

Broadcaster selfBroadcaster = (Broadcaster) session.getAttribute(sessionId);

BroadcasterFactory.getDefault().add(selfBroadcaster, name);

Now the global broadcaster. The logic here is, you create a broadcaster from the first resource and then add each resource as they log in.

Broadcaster globalBroadcaster;

globalBroadcaster = BroadcasterFactory.getDefault().lookup(DefaultBroadcaster.class, GLOBAL_TOKEN, false);
                if (globalBroadcaster == null) {
                  globalBroadcaster = selfBroadcaster;

                    } else {
                        BroadcasterFactory.getDefault().remove(
                                globalBroadcaster, GLOBAL_TOKEN);
                        AtmosphereResource r = (AtmosphereResource) session
                                .getAttribute("atmoResource");
                        globalBroadcaster.addAtmosphereResource(r);

                    }
                    BroadcasterFactory.getDefault().add(globalBroadcaster,
                            GLOBAL_TOKEN);

Finally, you can broadcast to Single connection or Globally to all connections as follows:

// Single Connection/Session
Broadcaster singleBroadcaster= BroadcasterFactory.getDefault().lookup(
                            DefaultBroadcaster.class, name);
singleBroadcaster.broadcast("Only for you");

// Global 
Broadcaster globalBroadcaster = BroadcasterFactory.getDefault().lookup(DefaultBroadcaster.class,GLOBAL_TOKEN, false);
globalBroadcaster.broadcast("Global message to all");

To send message to partner, just lookup the broadcaster for the partner and do the same as above for single connection.

Hope this helps someone who tries to achieve the same.
There may be better ways of doing this.
I think I will have to use this approach until someone suggests a better solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文