`

练习写个SGS的flash socket策略服务器

阅读更多

    http://duker.iteye.com/blog/209040上面提到flash socket的策略服务器问题如何用MINA2来解决。另外,在http://code.google.com/p/hudo/上的hudo as3 网络通信框架也提出使用一个简单的java程序监听843端口。网上介绍的解决方法很多,例如http://bbs.9ria.com/viewthread.php?tid=15182

    这个问题源于Actionscript3网络通信的特殊性——在通信之前必须(哪怕你代码里没有明显的程序表现)进行一次的策略请求。类似于html协议的策略文件和js的策略文件,只不过用tcp协议。SGS是开源的网游服务器引擎,但没有解决此问题的直接方法,我觉得用mina1.1.7解决这个问题比较方便,就试着写写,觉得还可行(至少hudo的demo可以用这种方法)。

    我的思路是,添加一个SGS服务,然后开mina服务器监听843端口,如果有合适的输入就返回crossdomain.xml开放端口。

    声明几点,一,我开一个SGS所以不会出现843端口冲突问题,二,我不知道代码是否经得起高并发——没有跨域策略文件,flash将无法进行任何socket连接,那是非常致命的问题。

    用hudo的demo来说:

    首先,修改SGS的配置文件conf\sgsApp.properties

# This is the properties file for running the MUDServer application

com.sun.sgs.app.name=thServer
com.sun.sgs.app.root=data/thServer
com.sun.sgs.app.port=23
com.sun.sgs.impl.transport.tcp.listen.port=23
com.sun.sgs.app.listener=thgame.GameChannels


# SGS 0.9.5.1-r3730
# see com.sun.sgs.impl.kernel.ServiceConfigRunner:fetchServices()
# My own service , use ":" to split
#com.sun.sgs.app.services=thgame.FlashPolicyServiceImpl
# Managers may be "", but CANNOT delete this line
#com.sun.sgs.app.managers=

# SGS 0.9.9
# see com.sun.sgs.impl.kernel.Kernel:fetchServices()
# My own service , use ":" to split
com.sun.sgs.services=thgame.FlashPolicyServiceImpl
# Managers may be "", but CANNOT delete this line
com.sun.sgs.managers=

 

注意,0.9.5和0.9.9不同,com.sun.sgs.app.* 和 com.sun.sgs.*,而且managers都不可以省略,详细可以参考SGS源代码。然后就是写那个thgame.FlashPolicyServiceImpl类了

 

package thgame;

import com.sun.sgs.kernel.ComponentRegistry;
import com.sun.sgs.service.Service;
import com.sun.sgs.service.TransactionProxy;
import java.util.Properties;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.common.DefaultIoFilterChainBuilder;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.IoAcceptorConfig;
import org.apache.mina.filter.LoggingFilter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;

/**
 * Simple Service implementation. <p> 
 */
public class FlashPolicyServiceImpl implements Service {
    /** Choose your favorite port number. */
    private static final int PORT = 843;
    

        
    public FlashPolicyServiceImpl(Properties properties,
		      ComponentRegistry systemRegistry,
		      TransactionProxy txnProxy)
			throws Exception
	{
    	System.out.println("FlashPolicyServiceImpl construct");
    	
    	//退出函数后线程仍存在
    	IoAcceptor acceptor = new SocketAcceptor();
    	IoAcceptorConfig config = new SocketAcceptorConfig();
    	DefaultIoFilterChainBuilder chain;

        chain = config.getFilterChain();
        
    	/**
    	 * 启用/禁用 SO_REUSEADDR 套接字选项。
    	 * 超过一个的套接字绑定到相同的套接字地址。
    	 * 如果此功能不受支持,则 getReuseAddress() 将始终返回 false
    	 */
    	//((SocketAcceptorConfig)config).setReuseAddress(true);
    	//System.out.println("getReuseAddress:" + ((SocketAcceptorConfig)config).isReuseAddress());
    	/**
    	 * 重复加logger会抛异常
    	 */
    	//chain.addLast("logger", new LoggingFilter());
        
        /**
         * 文本模式
         */
        //chain.addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory()));
        
        // Bind
        try {
			acceptor.bind(new InetSocketAddress(PORT), new FlashPolicyProtocolHandler(), config);
			System.out.println("FlashPolicyServiceImpl Listening on port " + PORT);    
        } catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
        
    	return;
	}
    
    public String getName() {
    	System.out.println("FlashPolicyServiceImpl ready");
    	
    	return toString();
    }

    public void ready() { 
    	
        return;
    }

    public void shutdown() {
    	System.out.println("FlashPolicyServiceImpl shutdown");
    }
}

 

再加上最为重要的handler就大功告成

package thgame;

import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;

import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.apache.mina.common.ByteBuffer;


public class FlashPolicyProtocolHandler extends IoHandlerAdapter {	
    private static String POLICY_FILE = "<cross-domain-policy>" + 
    	"<site-control permitted-cross-domain-policies=\"all\"/>" +
    	"<allow-access-from domain=\"*\" to-ports=\"*\" />" +
    	"</cross-domain-policy>";	
    
	private Charset ch = Charset.forName("utf-8");     
	private CharsetDecoder decoder = ch.newDecoder();  
	private CharsetEncoder encoder = ch.newEncoder();
    
    public void exceptionCaught(IoSession session, Throwable cause) {
        //cause.printStackTrace();
        // Close connection when unexpected exception is caught.
        session.close();
    }
   
	@Override
    public void messageReceived(IoSession session, Object message) {
        try {
			//System.out.println("received...");
			if(! (message instanceof ByteBuffer)) {
				session.close();
				return ;
			}
			
			ByteBuffer rb = (ByteBuffer) message;
			String str = rb.getString(decoder);
			
			//System.out.println(str);
			
			if(str.equals("<policy-file-request/>")){
	        	//System.out.println("<policy-file-request/>");
	        	ByteBuffer wb = ByteBuffer.allocate(POLICY_FILE.length());
				wb.putString(POLICY_FILE, encoder);
	            /**
	             * ByteBuffer必须flip
	             */
				wb.flip();
	            session.write(wb);
	        }
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
		}
    }
}
	

 

个人认为flash虽然对策略文件很重视,但通常只会在通信前读一次,以后不会再读,所以对服务器性能影响不会太大。

 

----------------------------------------------

 

补注:

由于这个问题是SGS上(试验性质)。

真实世界中,有人遇到端口连接过多而无法读出策略xml的情况(在广州交流会上听到)

所以这个问题在高并发情况下还挺复杂,并不是简单写个adapter类就能解决。

 

 

 

---------------------------------------------------

 

20100927补注:

除了策略文件外,想起来还遗漏掉flash开发中一个非常重要的问题,就是本地信任:

http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html

 

如果使用fd的话,还会出现一种情况,你直接打开是本地文件不信任,但用FD会本地信任,而且还会影响到直接打开——以后打开swf也变成本地信任。原因是有个配置文件在起作用,它记录下曾经用FD打开过的swf,致使它们本地信任(可以访问本地文件)

假设使用Administrator用户,则在Windows XP的目录

C:\Documents and Settings\Administrator\Application Data\Macromedia\Flash Player\#Security\FlashPlayerTrust

的xxx.cfg就是造成本地信任的原因!

如果想模拟真实的用户系统(没有调试过flash),必须把此目录下的文件全部删除!否则不信任对话框不弹出!

详细请参考:

http://www.cc-space.com/?p=401

 

 

 

 

 ------------------------------------------------------

 

 

assql有更详细的关于策略服务器的搭建方法(使用各种编程语言),可以参考:

http://code.google.com/p/assql/wiki/SecurityInformation

 

另外socket的策略文件除了可以在843端口读,还可以在连接中的端口读取,可以根据项目需要选择。

 

 

 

--------------------------------------------------------

 

mina2以后的线程池可能需要手工关闭(或者用System.exit(0))

下面代码仅供参考

 

 

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;

import org.apache.mina.core.service.SimpleIoProcessorPool;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioProcessor;
import org.apache.mina.transport.socket.nio.NioSession;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

...

/**
 * 服务器实例
 * @author Administrator
 *
 */
public final class PackServer {
    private static final Logger LOG = Logger.getLogger(PackServer.class);
    private static ExecutorService executorService = 
	Executors.newCachedThreadPool();
    private static SimpleIoProcessorPool<NioSession> pool = 
	new SimpleIoProcessorPool<NioSession>(
	    NioProcessor.class, 
	    executorService, 
	    Runtime.getRuntime().availableProcessors() + 1);

    private static NioSocketAcceptor acceptor = new NioSocketAcceptor(pool);

    public static void startSever() throws IOException {
	acceptor.setHandler(new PackServerHandler());
	acceptor.setReuseAddress(true);
	acceptor.bind(new InetSocketAddress(GlobalConfig.DEFAULT_PORT));
	LOG.info("Listening on port " + GlobalConfig.DEFAULT_PORT);
    }

    public static void stopServer() {
	if (acceptor != null) {
	    //关闭线程池,否则无法退出
	    executorService.shutdown();
	    //关闭服务器路由总开关
	    acceptor.unbind();
	    acceptor.dispose();
	}
    }

    // ---------------------------------------------
    private PackServer() {

    }
}

 

-----------------------------------------------

 

这里有个jboss netty版的flash策略服务器实现:

 

https://github.com/cgbystrom/netty-tools/blob/master/src/main/java/se/cgbystrom/netty/FlashPolicyHandler.java

 

 

 

 

 

 

分享到:
评论

相关推荐

    死活练习2062题.sgs

    死活练习2062题.sgs

    LU-SGS.rar_LU SGS_LU-SGS_LUSGS格式_sgs_流体

    在研究和应用LU-SGS算法时,通常会关注以下几个方面: 1. **网格生成**:网格的质量直接影响到数值模拟的精度。网格可以是结构化的(如矩形网格)或非结构化的(如四面体网格),需要根据流场的复杂性选择合适的...

    sgs-server-dist文件

    "sgs-server-dist"文件是针对游戏服务器开发的一个软件包,主要包含了Darkstar项目的核心组件和服务端相关的资源。Darkstar是一个开源的游戏服务器平台,专为大规模多人在线游戏(MMO)设计,它提供了高性能、可扩展...

    sgs接口协议

    SGS接口协议是3GPP(Third Generation Partnership Project)通信标准中的一个重要组成部分,它定义了移动网络中的MME(Mobility Management Entity)和MSC(Mobile Switching Center)之间的交互方式。MME是LTE网络...

    SGS核心代码分析.docx

    SGS(Sun Game Server)是一款由Sun Microsystems开发的游戏服务器框架,其设计目标是为了支持大型在线游戏的运行和服务。它提供了丰富的API和服务,使得开发者能够更加专注于游戏逻辑的编写而不用担心底层网络通信...

    这是一个关于SGS-AS3 的两人游戏

    5. **网络编程**: 使用Socket或WebSocket等技术实现客户端与服务器的实时通信,确保游戏数据在两个玩家之间准确无误地传输。 6. **图形渲染**: ActionScript 3 支持Flash Player API,可以创建丰富的2D图形,包括...

    SGS申请表空白

    在该“SGS申请表空白”中,我们可以看到以下几个关键知识点: 1. **申请表格内容**:申请表包括了客户的基本信息,如公司名称、地址、联络人信息以及样品的详细信息,例如样品名称、型号、料号、批号和主要成分。...

    sun game server (sgs)初探

    总之,"sun game server (sgs)初探"这篇博文及其相关资源为读者提供了一个了解和学习游戏服务器开发的窗口,通过源码分析和工具使用,开发者可以掌握更多关于构建高性能、高并发游戏服务器的知识和技术。这不仅对于...

    sgs-client 文件

    "darkstar"可能是一个与之配套的服务器组件,或者是一个特定的游戏服务器实现,它可能基于类似的设计理念,为sgs-client提供了接口和通信协议。 "sgs-client-0.10.1"这个文件名可能表示这是sgs-client的0.10.1版本...

    CF-Root-SGS3-v6.0.zip_CF-Root-SGS3-V6.0_ROOT

    标签"cf-root-sgs3-v6.0 root"突出了这个工具包与三星Galaxy S3(型号通常表示为SGS3)和root权限获取的关联,其中"v6.0"表示这是该工具的第六个主要版本。 在压缩包的文件名称列表中,只有一个文件:"CF-Root-SGS3...

    拨号器格式SGS

    拨号器格式SGS是一种专为Samsung Galaxy S(简称SGS)系列智能手机设计的拨号程序格式,它允许用户通过手机进行数据连接,通常用于通过ADSL(Asymmetric Digital Subscriber Line)方式接入互联网。在本压缩包中,...

    网络技术-网络基础-第三方商业检测认证机构SGS集团省略中国的整合营销与品牌传播策略研究.pdf

    【网络技术-网络基础】中的知识点主要涉及到第三方商业检测认证机构SGS集团在中国市场的整合营销与品牌传播策略。SGS是一家全球领先的独立检验、验证、测试和认证机构,其服务范围涵盖消费品检测、工业领域服务以及...

    sgs2toext4

    本帖最后由 ylf3ys5 于 2012-9-7 17:23 编辑 还在羡慕各位达人总自己制作精美的ROM,还为不小心删除某个部件求爷爷求奶奶找人提取吗?看完后你将能解决上面的苦恼。 第一种:tar或ZIP直接解压里面有system文件,...

    2011SGS报告中文版

    该报告主要涉及了重金属含量、阻燃剂成分以及卤素含量的检测,并且依据了多个国际测试标准进行。下面将对这份报告中的关键知识点进行详细的解读与总结。 ### 报告基本信息 - **测试报告编号**:CANEC1101838602 - ...

    sgs.zip_Matlab可运行_sgs_遗传算法 可_遗传算法图_遗传算法程序

    "sgs.m"提供了一个基础框架,用户可以通过修改这个框架,将其应用于更广泛的优化问题中。 总结,"sgs.zip"是一个实用的Matlab遗传算法实例,不仅能够帮助初学者快速理解和掌握遗传算法的基本原理,也为有经验的...

    FLASH WEBGame 多人游戏社区(源码+服务端)

    在这个项目中,服务端采用了SGS(Smart Game Server)技术,这是一种专门为游戏设计的服务器框架,能够高效处理游戏逻辑和玩家同步问题。SGS RPG地图多人同步,表明该系统支持角色扮演游戏(RPG)的地图设定,并且...

    分离焦虑规定sgs

    #### 六、应对策略 **1. 预先告知** - 在离开孩子之前,提前用孩子能够理解的方式告诉他们即将发生的分离。 **2. 保持一致性** - 建立稳定的日常生活规律,让孩子知道何时会有分离发生,帮助他们建立预期。 **3. ...

    c#sgs代码原

    结合以上信息,我们可以推测这个项目可能是一个基于C#的游戏开发项目,名称为SGS,可能是一个类似《三国杀》的卡牌策略游戏。源代码包含了游戏的逻辑、界面、网络通信等部分,而分卷的RAR文件则包含了项目的资源、...

    费斯托SGS系列关节轴承.PDF

    费斯托SGS系列关节轴承PDF,费斯托关节轴承CRSGS、SGS以及外围元件、产品范围等的介绍

Global site tag (gtag.js) - Google Analytics