Apache mina 2.0.1 和 AS3 Socket 进行通讯(处理粘包问题)

本文介绍了一种使用Apache Mina的PrefixedStringCodecFactory解决Socket通信中粘包问题的方法,并提供了服务端及Flex客户端的具体实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://wuhui0915.blog.163.com/blog/static/2186455320109292221272/

Socket 的粘包问题我这里就不多说了,网上到处是,本人也碰到了这个问题,在网上找了一下资料,研究了一下,终于解决了这个问题,以下是我的处理方式,我用了 Apache mina 2.0.1 自带的PrefixedStringCodecFactory这个数据编解码器,它的处理方式是包含一个发送数据的长度,然后根据长度来得到你发送的数据包,这样就不会出现粘包的问题。
如图所示:

Apache mina 2.0.1 和 AS3 Socket 进行通讯(处理粘包问题) - ←╊咆哮 - 我心疯狂
 

 发送的时候是这样,接收的时候也是这样,所以要在客户端自己做处理

开发环境:
MyEclipse6.5 + JDK1.6.11 + FlexBuilder 3

准备工作:
1.去 http://www.apache.org 下载 apache-mina-2.0.1-bin;
2.建立一个 javaProject 将 apache-mina-2.0.1\dist\mina-core-2.0.1.jar 和 apache-mina-2.0.1\lib\slf4j-api-1.5.11.jar 导入;
3.去 http://www.slf4j.org 下载 slf4j-1.5.11;
4.将 slf4j-1.5.11\slf4j-simple-1.5.11.jar 导入 (这个jar包是必须的,否则运行的时候会报错)
jar包全部导入后如图

Apache mina 2.0.1 和 AS3 Socket 进行通讯(处理粘包问题) - ←╊咆哮 - 我心疯狂

 服务端代码:
代码结构(一共3个类,用来测试用的,至于接收到数据后你怎么处理,你自己在加):
MinaServer.java
MinaSessionHandle.java
MinaSocketTest.java

MinaServer.java
package com.derek.socket.mina;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.prefixedstring.PrefixedStringCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class MinaServer {

    private static final int PORT = 12727;

    final IoAcceptor acceptor = new NioSocketAcceptor();

    public MinaServer() {
        acceptor.setHandler(new MinaSessionHandle());
        acceptor.getFilterChain().addLast("codec",
                new ProtocolCodecFilter(new PrefixedStringCodecFactory(Charset.forName("UTF-8"))));
        try {
            acceptor.bind(new InetSocketAddress(PORT));
            System.out.println("Game Socket Server Started...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void shutdown() {
        acceptor.unbind();
        acceptor.dispose();
    }
}


MinaSessionHandle.java
package com.derek.socket.mina;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;

public class MinaSessionHandle extends IoHandlerAdapter {

    @Override
    public void sessionCreated(IoSession session) throws Exception {
        System.out.println("the new session is connecting"); 
    } 
   
   
/**
      *  注意:这里是
PrefixedStringCodecFactory 已经处理过的数据,只接收内容部分,数据长度部分将被过滤掉
      */
    @Override 
    public void messageReceived(IoSession session, Object message) throws Exception {
        try {

            System.out.println("****"+message+"****"); 
            // TODO 这里定义你自己的方法
            //
注意:这里发送最后也是通过PrefixedStringCodecFactory 处理过后的数据(包括文件数据长度和内容两部分)
            session.write(message.toString());  //发送回客服端(测试用)
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
   
    @Override
    public void exceptionCaught(IoSession session, Throwable cause)
            throws Exception {
        System.out.println("客户端 " + session.getRemoteAddress() + " 关闭了连接");
        session.close(false);
    }
}

MinaSocketTest.java 
package com.derek.socket.mina;

public class MinaSocketTest extends Thread{

    public void run () {
        new MinaServer();
    }
    public static void main(String args[]){
        MinaSocketTest test = new MinaSocketTest();
        test.start();
    }
}


客服端:
建一个测试的类就行
SocketTest.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()">
    <mx:Script>
        <![CDATA[
            import flash.net.Socket;
            import com.adobe.serialization.json.JSON;
           
            private var socket:Socket;
           
            private var socketlen:int = 0;
           
            private function init():void
            {
                socket = new Socket();
                //连接 Socket
                socket.connect("127.0.0.1",12727);
               
                //注册 Socket连接事件
                socket.addEventListener(Event.CONNECT,socketConnect);
                //注册 Socket关闭事件
                socket.addEventListener(Event.CLOSE,socketClose);
                //注册 安全错误事件
                socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityError);
                //注册 IO错误事件
                socket.addEventListener(IOErrorEvent.IO_ERROR,socketIOError);
                //注册 处理Socket接收数据事件
                socket.addEventListener(ProgressEvent.SOCKET_DATA,socketData);
            }
           
           
            //连接建立
            private function socketConnect(event:Event):void{
                /**
                 * 向服务器发送数据
                 */
                this.sendData("-------已经建立连接");
            }
           
            private function sendAllData():void{
                for (var i:int=0;i<100;i++)
                {
                    this.sendData("IUUUIIIOIU");
                    this.sendData("3399TT999");
                    this.sendData("091567");
                    this.sendData("3odjs9r000sfdjkfjsldwe34");
                }
            }
           
            //连接关闭
            private function socketClose(event:Event):void{
                trace("----链接关闭");
                socket.close();
                socket = null;
            }
           
            //连接关闭
            private function thisSocketClose():void{
                trace("--this--连接关闭--");
                socket.close();
                socket = null;
            }
           
            //安全错误
            private function securityError(event:SecurityErrorEvent):void{
                trace("----安全错误");
                socket.close();
                socket = null;
            }
           
            //IO错误
            private function socketIOError(event:Event):void{
                trace("----IO错误");
                socket.close();
                socket = null;
            }
           
            //发送数据
            private function sendData(data:String):void{
                if(socket == null) return;
                if(data==null||data.length==0) return;
                var byte:ByteArray = new ByteArray();
                byte.writeUTFBytes(data);
                //下面注意:
                socket.writeInt(byte.length); //先写入数据的长度
                socket.writeBytes(byte); //再写入内容
                socket.flush();
            }

            //接收数据
            private function socketData(event:ProgressEvent):void{
               
                try{
                    while(true){
                        //先读取数据长度,再根据长度读取数据
                        if (socketlen == 0)
                        {
                            if (socket.bytesAvailable < 4) return;
                            socketlen = socket.readInt();
                            trace("****"+socketlen+"****");
                        }
                        if (socket.bytesAvailable < socketlen) return;
                        var msg:String = socket.readUTFBytes(socketlen);
                        socketlen=0;
                        trace("****"+msg+"****");
                        // TODO 这里定义你自己的方法
                    }
                }catch(e:Error){
                    trace(e.message);
                }
            }
        ]]>
    </mx:Script>
    <mx:Button x="211" y="250" label="发送" click="sendAllData();"/>
    <mx:Button x="291" y="250" label="关闭" click="thisSocketClose();"/>
</mx:Application>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值