本文介绍使用java的Mina框架,来编写socket服务器,以及和swf文件直接进行socket连接。
需要用到mina2.0的jar包 大家自己去找吧。
废话不说,直接先上服务端代码:
main.java
import java.io.IOException;
import com.game.action.StartGameHandler;
import com.game.server.TcpServer;
import com.game.service.InitGameService;
public class main {
public static void main(String[] string) throws Exception {
new StartGameHandler();
InitGameService.getService().init();//初始化信息
TcpServer tcpServer = new TcpServer();
tcpServer.serverStart();
tcpServer.securityStart();
}
}
ServerHandler .java
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoSession;
public class ServerHandler implements IoHandler{
private IoAcceptor acceptor;
private static ServerHandler handler = new ServerHandler();
public static ServerHandler getInstance() {
if(handler == null){
handler = new ServerHandler();
}
return handler;
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
//在此地接收信息。
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println("联机关闭");
return;
}
@Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("联机创建了");
}
@Override
public void sessionIdle(IoSession arg0, IdleStatus arg1) throws Exception {
// TODO Auto-generated method stub
System.out.println("用户连接了");
}
@Override
public void sessionOpened(IoSession session) throws Exception {
// TODO Auto-generated method stub
return;
}
public IoAcceptor getAcceptor() {
return this.acceptor;
}
public void setAcceptor(IoAcceptor acceptor) {
this.acceptor = acceptor;
}
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
System.out.println("出错了");
cause.printStackTrace();
}
}
TcpServer.java
package com.game.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import com.game.action.GameHandler;
public class TcpServer {
public void serverStart(){
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getSessionConfig().setReadBufferSize(1024000);
acceptor.getFilterChain().addLast( "logger", new LoggingFilter());
acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ),LineDelimiter.NUL,LineDelimiter.NUL)));
GameHandler handler = GameHandler.getInstance();
acceptor.setHandler(handler);
try {
acceptor.bind(new InetSocketAddress(6060));
System.out.println("TCP端口绑定: "+6060);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("TCP服务监听开始...... ");
}
public void securityStart(){
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getSessionConfig().setReadBufferSize(1024000);
acceptor.getFilterChain().addLast( "logger", new LoggingFilter());
acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ),LineDelimiter.NUL,LineDelimiter.NUL)));
SecurityHandler handler = SecurityHandler.getInstance();
acceptor.setHandler(handler);
try {
acceptor.bind(new InetSocketAddress(843));
System.out.println("TCP端口绑定: "+843);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("TCP服务监听开始...... ");
}
}
安全策略端口监听:
SecurityHandler .java
import java.util.List;
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoSession;
public class SecurityHandler implements IoHandler{
private IoAcceptor acceptor;
private String securityWords = "<policy-file-request/>";
private final String securityXml = "<?xml version='1.0'?>" +
"<cross-domain-policy>" +
"<allow-access-from domain='*' to-ports='*'/>" +
"</cross-domain-policy>";
private static SecurityHandler handler = new SecurityHandler();
public static SecurityHandler getInstance() {
if(handler == null){
handler = new SecurityHandler();
}
return handler;
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
System.out.println("843:"+message);
session.write(securityXml+ "\0");
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void sessionClosed(IoSession session) throws Exception {
return;
}
@Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("联机创建了");
}
@Override
public void sessionIdle(IoSession arg0, IdleStatus arg1) throws Exception {
// TODO Auto-generated method stub
System.out.println("用户连接了");
}
@Override
public void sessionOpened(IoSession session) throws Exception {
// TODO Auto-generated method stub
return;
}
public IoAcceptor getAcceptor() {
return this.acceptor;
}
public void setAcceptor(IoAcceptor acceptor) {
this.acceptor = acceptor;
}
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
System.out.println("出错了");
cause.printStackTrace();
}
}
客户端代码:
package
{
import flash.display.MovieClip;
import flash.events.*;
import flash.net.Socket;
import flash.net.XMLSocket;
import flash.system.Security;
import flash.system.SecurityDomain;
public class SocketClient {
private var socket:Socket;
private var xmlSocket:XMLSocket = new XMLSocket();
private var connect:Boolean = false;
private var _obj:Object = this;
private static var client:SocketClient = null;
//private var ip:String = "192.168.1.101";
private var ip:String = "127.0.0.1";
private var surityStr = "xmlsocket://"+ip+":843";
private var port:int = 6060;
public function SocketClient() {
initApp();
}
/**单例模式**/
public static function getInstance():SocketClient{
if(client==null)
{
client = new SocketClient();
}
return client;
}
private function initApp():void{
if(!xmlSocket.connected)
{
initXMLSocket();
}
}
private function initXMLSocket() {
Security.loadPolicyFile(surityStr);
xmlSocket.connect(ip,port);
xmlSocket.addEventListener(Event.CONNECT,connectionFun);
xmlSocket.addEventListener(Event.CLOSE,closeFun);
}
public function setBackFunction(fun:Function){
xmlSocket.addEventListener(DataEvent.DATA,fun);
}
private function connectionFun(event:Event):void{
trace("已经成功连接到服务器\n");
}
/**
**设置回调方法
***/
private function closeFun(event:Event):void{
trace("已经断开服务器\n");
client = null;
}
public function receiveMsg(event:DataEvent):void{
trace("接收到消息"+event.data);
}
public function removeListener(fun:Function) {
xmlSocket.removeEventListener(DataEvent.DATA ,fun);
}
/**
*向服务端发送 xml 数据
***/
public function sendXml(xml:String):void{
try{
xmlSocket.send(xml.toString());
}catch(e:Error){
client = null;
}
}
}
}
实例化这个类之后,直接调用 sendXml("参数") 这个方法,即可发送socket消息。
Security.loadPolicyFile(surityStr);//这个是策略信息。
向843端口发送信息后,843端口返回策略信息,即能完成socket连接。
如果没有策略信息,是可以连接到6060端口,但是连接后,马上会断掉,所以无法进行socket通信。
注意:发布的时候,flash cs 要在发布配置里面 配置好“只访问网络”。
如果发布配置不设置好,前面的代码我测试是无法通过的。本地测试OK。只打开swf文件就无法正常通信。这点我折腾了很久。