ProjectDarkStar服务器端开发文档(七)Hello Channels

转自:http://www.david0446.com/?p=72

第六课:Hello Channels

The previous lessons have introduced the Task Manager and Data Manager. The final standard manager is the Channel Manager. The core of the PDS provides us with basic client/server communications. For simple games, this may be enough. However, for games that organize players into groups, either to isolate game sessions (such as in many casual and fast action games), or to tame the n-squared user-to-user communications scaling issues inherent in massive numbers of simultaneous players, something with lower overhead and more control is required.

       之前的课程介绍了任务管理器(Task Manager)和数据管理器(Data Manager)。最后一个标准管理器是通道管理器Channel Manager)。PDS的核心代码为我们提供了基本的客户端/服务器通信。对于一个简单的游戏来说,这就足够了。然而,对于那些要将玩家组队,不是要隔离游戏会话(就像许多即时性操作游戏),就是要解决不规则的用户对用户的通信,在大量的玩家同时发生时。那就要求更低的开销和更有效的控制。

The Channel Manager provides publish/subscribe channels. The server application can create these channels and then assign users to one or more of them. Communication between users in a channel does not involve the Task or Data Manager.

       通道管理器提供“发布/订阅”通道。服务器程序可以创建这些通道,然后使用它们其中的一个或者更多。在一个通道中的用户之间的通信不会牵涉到任务或数据管理器。

1.编写HelloChannels

The HelloChannels Managed Object is similar to our previous AppListener implementations with the addition that it opens two reliable channels, Foo and Bar.

       HelloChannels这个管理对象很像我们前面的AppListener实现类,它打开了两个可靠的通道,FooBar

HelloChannels

/*
 * Copyright 2007-2009 Sun Microsystems, Inc.
 *
 * This file is part of Project Darkstar Server.
 *
 * Project Darkstar Server is free software: you can redistribute it
 * and/or modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation and
 * distributed hereunder to you.
 *
 * Project Darkstar Server is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see .
 
*/
package com.sun.sgs.tutorial.server.lesson6;

import java.io.Serializable;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.sgs.app.AppContext;
import com.sun.sgs.app.AppListener;
import com.sun.sgs.app.Channel;
import com.sun.sgs.app.ChannelManager;
import com.sun.sgs.app.ClientSession;
import com.sun.sgs.app.ClientSessionListener;
import com.sun.sgs.app.Delivery;
import com.sun.sgs.app.ManagedReference;

/**
 * Simple example of channel operations in the Project Darkstar Server.
 * 
 * 
 * Extends the {
@code HelloEcho} example by joining clients to two channels.
 
*/
public class HelloChannels implements Serializable, AppListener {
    
/** The version of the serialized form of this class. */
    
private static final long serialVersionUID = 1L;

    
/** The {@link Logger} for this class. */
    
private static final Logger logger = Logger.getLogger(HelloChannels.class
            .getName());

    
/* The name of the first channel {@value #CHANNEL_1_NAME} */
    
static final String CHANNEL_1_NAME = "Foo";

    
/* The name of the second channel {@value #CHANNEL_2_NAME} */
    
static final String CHANNEL_2_NAME = "Bar";

    
/**
     * The first {
@link Channel}. The second channel is looked up by name.
     
*/
    
private ManagedReference channel1 = null;

    
/**
     * {
@inheritDoc}
     * 
     * 
     * Creates the channels. Channels persist across server restarts, so they
     * only need to be created here in {
@code initialize}.
     
*/
    
public void initialize(Properties props) {
        ChannelManager channelMgr 
= AppContext.getChannelManager();

        
// Create and keep a reference to the first channel.
        Channel c1 = channelMgr.createChannel(CHANNEL_1_NAME, null,
                Delivery.RELIABLE);
        channel1 
= AppContext.getDataManager().createReference(c1);

        
// We don't keep a reference to the second channel, to demonstrate
        
// looking it up by name when needed. Also, this channel uses a
        
// {@link ChannelListener} to filter messages.
        channelMgr.createChannel(CHANNEL_2_NAME,
                
new HelloChannelsChannelListener(), Delivery.RELIABLE);
    }

    
/**
     * {
@inheritDoc}
     * 
     * 
     * Returns a {
@link HelloChannelsSessionListener} for the logged-in session.
     
*/
    
public ClientSessionListener loggedIn(ClientSession session) {
        logger.log(Level.INFO, 
"User {0} has logged in", session.getName());
        
return new HelloChannelsSessionListener(session, channel1);
    }
}

The HelloChannelsSessionListener is identical to HelloEchoSessionListener except for the constructor. When we create the session listener, we also join its session to two channels. One channel is passed in, while the second is looked up by name.

       HelloChannelsSessionListenerHelloEchoSessionListener除了构造器之外,其他地方没有区别。当我们创建了会话监听器,我们也将它的会话加入到了两个通道中。一个通道传进来,第二个通过名称查找。

The first channel.join is passed null for a ChannelListener, so all communication on it is only received by clients. The second channel joined however is given a channel listener. This will be called back whenever a message from this session is posted to that channel. The listener can examine the message and sender and decide to discard the message, send a different message to the channel, or send the original, unmodified message to the channel.

        第一个channel.joinChannelListener传递空值,所以,上面所有的通信只能由客户端接收。然而,第二个则给出了一个通道监听器。任何时候,会话里只要有消息传到通道,它都会进行回调。这个监听器可以检查消息,发送消息;也可以丢弃消息,并发送一条不同的消息到通道,或者发送原始的,没有被修改的消息到通道。

Note that, with this code, each session has it own listener for messages on the second channel. This is preferable to registering a single channel-wide listener, since messages from different clients can be processed in parallel. However, if your design really requires a single listener to all messages sent by any client on a channel, you would declare the listener as the second parameter to the createChannel call.

       这个代码中要注意的是,在第二个通道上每个会话都有它自己的消息监听器。这比注册一个单独的通道监听器更好,因为从不同客户端发来的消息可以被并行处理。然而,如果你的设计真的是在一个通道上注册一个独立的监听器来处理任何客户发来的所有的信息,你要申明这个监听器作为createChannel方法调用中的第二个参数。

HelloChannelsSessionListener

HelloChannelsChannelListener is a simple skeletal listener that just logs what it receives.

       HelloChannelsChannelListener是一个简单的监听器框架,它只记录接收了什么。

HelloChannelsChannelListener

/*
 * Copyright 2007-2009 Sun Microsystems, Inc.
 *
 * This file is part of Project Darkstar Server.
 *
 * Project Darkstar Server is free software: you can redistribute it
 * and/or modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation and
 * distributed hereunder to you.
 *
 * Project Darkstar Server is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see .
 
*/
package com.sun.sgs.tutorial.server.lesson6;

import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.sgs.app.Channel;
import com.sun.sgs.app.ChannelListener;
import com.sun.sgs.app.ClientSession;
import java.nio.ByteBuffer;

/**
 * Simple example {
@link ChannelListener} for the Project Darkstar Server.
 * 
 * 
 * Logs when a channel receives data.
 
*/
class HelloChannelsChannelListener implements Serializable, ChannelListener {
    
/** The version of the serialized form of this class. */
    
private static final long serialVersionUID = 1L;

    
/** The {@link Logger} for this class. */
    
private static final Logger logger = Logger
            .getLogger(HelloChannelsChannelListener.
class.getName());

    
/**
     * {
@inheritDoc}
     * 
     * 
     * Logs when data arrives on a channel. A typical listener would examine the
     * message to decide whether it should be discarded, modified, or sent
     * unchanged.
     
*/
    
public void receivedMessage(Channel channel, ClientSession session,
            ByteBuffer message) {
        
if (logger.isLoggable(Level.INFO)) {
            logger.log(Level.INFO, 
"Channel message from {0} on channel {1}",
                    
new Object[] { session.getName(), channel.getName() });
        }
        channel.send(session, message);
    }
}

2.运行HelloChannels

To try HelloChannels you need a client that will connect and allow you to talk on selected channels. One is provided in Lesson 2 of the Project Darkstar Client Tutorial

(com.sun.sgs.tutorial.client.lesson2.HelloChannelClient in tutorial-client.jar).

       运行HelloChannels你需要一个客户端,它会来连接,并且允许你和选择的通道进行对话。一个已经在Project Darkstar Client Tutorial文档中第二课提供了。

(com.sun.sgs.tutorial.client.lesson2.HelloChannelClient in tutorial-client.jar).

原文地址:https://www.cnblogs.com/sevenyuan/p/1609937.html