mina 接收数据问题

PlayMan 发布于 2010/01/25 02:57
阅读 6K+
收藏 1

不知道为什么,mina运行1段时间就会在接收数据出现问题!特别是客户端连发数据时!

正常时:
客户端发出:78 DA E3 E2 66 64 4E 64 61 64 04 00 02 4D 00 81
服务端接收: 78 DA E3 E2 66 64 4E 64 61 64 04 00 02 4D 00 81

异常时:
客户端发出:78 DA E3 E2 66 64 4E 64 61 64 04 00 02 4D 00 81
服务端接收: 78 DA E3 E2 66 64 4E 64 61 64 04 00 02 4D 00 81 78 DA E3 E2 66 64 4E 64
客户端发出:78 DA E3 E2 66 64 4E 64 61 64 04 00 02 4D 00 81
服务端接收: 4E 64 61 64 04 00 02 4D 00 81 <----这时就出错了!

应该是在decode时,缓冲中的数据里,有两个或以上有客户端写发出的数据,所以一读缓冲中的数据,就读多了,导致下次再读时数据不完整。
在网上找了很久,都找不到解决方法!
http://www.ibm.com/developerworks/cn/java/j-lo-mina2
这里提到 prefixedDataAvailable 会检查 消息头,但是我不知道怎样设置消息头。
有人对mina有研究吗?能帮帮我吗?

加载中
0
JavaGG
JavaGG

就是在协议的开头设一个长度,说明这个包有多小数据

0
P
PlayMan

我在Flash 设置信息头,信息头里记的是信息的长度,然後在mina里先读信息头里记的长度
这方法行,不过有5个以上客户端和每个客户端以200毫秒向服务器发送信息,服务端又开始异常。
我只新手,帮我看看有没有写错,下面附源码!

 Flash 发信息 

private function send(x:Number, y:Number):void {
	if (! _socket.connected) {
		return;
	}
	var bytes:ByteArray = new ByteArray();
	if (_id==0) {
		bytes.writeObject({event:"init",x:x,y:y});
	} else {
		bytes.writeObject( { event:"move", x:x, y:y } );
	}
	bytes.compress();
	_socket.writeInt(bytes.length);//设置信息头 信息长度 
	_socket.writeBytes(bytes);//信息内容 用 AMF3 加码
	_socket.flush();
}


 Java AMF3Decoder

package com.klstudio.chat.filter.amf3;

import java.util.zip.InflaterInputStream;
import java.io.*;
import java.net.*;
import java.io.DataInputStream;
import java.io.UnsupportedEncodingException;

import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;
import flex.messaging.io.amf.ASObject;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

public class AMF3Decoder extends CumulativeProtocolDecoder {

    private final AttributeKey POLICY = new AttributeKey(getClass(), "policy");
    private final String security = "<policy-file-request/>";
    private final SerializationContext context = new SerializationContext();
    private final Amf3Input amf3in;

    public AMF3Decoder() {
        amf3in = new Amf3Input(context);
    }

    @Override
    protected boolean doDecode(IoSession session, IoBuffer in,
            ProtocolDecoderOutput out) throws Exception {
        
       int len = in.getSlice(0, 4).getInt(); //读信息头里的信息长度
       byte[] buf = new byte[len+4];
       ByteArrayInputStream bais = new ByteArrayInputStream(buf);                
       DataInputStream dis = new DataInputStream(bais);
       InflaterInputStream ifis = new InflaterInputStream(dis);
       amf3in.setInputStream(ifis);
                try {
                        in.position(4);
                        in.limit(len+4);
                        InputStream is = in.asInputStream();
                        is.read(buf);
                        is.close();
                } catch (IOException e) {                        
                        e.printStackTrace();                        
                }
                Object message = amf3in.readObject();
                if (message instanceof ASObject) {
                    out.write(message);                    
                    in.free();
                    return true;
                } else {
                    in.free();
                    return false;
                }                   
    }
}

0
Jackarain
Jackarain

拆包组包。。。

0
P
PlayMan

引用来自“jack.wgm”的帖子

拆包组包。。。

 我是新手能给些例如参考吗?或者能详细说说怎样拆包组包吗?

0
s
sunmoon

楼主,我也遇到这样的问题,请问你解决了吗?

0
平安北京

对于网络中粘包的问题,你只能自己去拆包组包,你必须在数据包中定义包的长度,根据这个长度去读取数据。

0
f
fungs

可以继承MessageDecoder实现数据验证

0
阿影
阿影

给你一个通用的消息结构。

 消息类型| 主消息长度 [| 其它定长数据]  | 主消息内容(长度由上上一个结构指定)

  2 byte | 4 byte     [| 其它定长数据]  | n byte

写 Message Encoder Decoder 解析验证数据。

可以使用Mina给出的例子 sumup 中的解码/编码器。

返回顶部
顶部