java mina 组包_模拟实现 网络拥堵的状况 mina | 学步园

在mina的ProtocolDecoder合并 未完整发送的数据包。

由于Socket方面的基础不扎实,对nio的理解不深入,

这几天看了Apache MINA 2.0.0-M1 里的相关代码,才明白了nio的处理和我先前理解的不一样

虽然在 http://618119.com/archives/2008/03/07/73.html

考虑到了客户端把多个PDU数据包一次发送的情况,却没有考虑到PDU数据包被分片发送的情况,

于是以前写的ProtocolDecoder在网络环境恶劣或客户端没有整包发送数据的情况下,就会出现问题,

在ProtocolDecoder增加了合并PDU数据包的处理,经过测试,PDU数据包分片发送的时候,服务端也能够正常解析了。

客户端往Socket发送数据包的代码:

[code]

byte bo[] = bao.toByteArray();

sc.getOutputStream().write(bo, 0, 4);//先发四个字节

Thread.sleep(500);

sc.getOutputStream().write(bo, 4, 8);//再发送8个字节

Thread.sleep(500);

sc.getOutputStream().write(bo, 12, bo.length - 12);//再把剩余的数据发过去

[/code]

服务端改进后的代码:

[code]

package com.lizongbo.smpp.server.codec;

import org.apache.mina.common.AttributeKey;

import org.apache.mina.common.IoBuffer;

import org.apache.mina.common.IoSession;

import org.apache.mina.filter.codec.ProtocolDecoder;

import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import com.lizongbo.smpp.BadCommandIDException;

import com.lizongbo.smpp.message.SMPPPacket;

import com.lizongbo.smpp.util.SMPPIO;

import com.lizongbo.smpp.util.PacketFactory;

public class SMPPProtocolDecoder implements ProtocolDecoder {

private static final AttributeKey BUF_BYTE = new AttributeKey(

SMPPProtocolDecoder.class, "bufb");

public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)

throws Exception {

try {

IoBuffer bufTmp = null;

byte[] buf = (byte[]) session.getAttribute(BUF_BYTE);

if (buf == null) {

// System.out.println("没有尚未处理的数据");

bufTmp = in;

} else {

// System.out.println("合并尚未处理的数据");

bufTmp = IoBuffer.allocate(buf.length + in.remaining());

bufTmp.setAutoExpand(true);

bufTmp.put(buf);

bufTmp.put(in);

bufTmp.flip();

}

while (bufTmp.remaining() >= 4

&& bufTmp.remaining() >= bufTmp.getInt(bufTmp.position())) {// 循环处理数据包

int dataLen = bufTmp.getInt(bufTmp.position());

byte[] b = new byte[dataLen];

bufTmp.get(b);

SMPPPacket pak = null;

int id = -1;

id = SMPPIO.bytesToInt(b, 4, 4);

pak = PacketFactory.newInstance(id);

if (pak != null) {

pak.readFrom(b, 0);

out.write(pak);

}

}

if (bufTmp.hasRemaining()) {// 如果有剩余的数据,则放入Session中

byte[] tmpb = new byte[bufTmp.remaining()];

bufTmp.get(tmpb);

session.setAttribute(BUF_BYTE, tmpb);

}

}

catch (BadCommandIDException ex) {

ex.printStackTrace();

}

}

public void dispose(IoSession session) throws Exception {

}

public void finishDecode(IoSession session, ProtocolDecoderOutput out)

throws Exception {

}

}

[/code]

调试日志如下:

(一个数据包被分为三段发送,服务端收到之后重新组包解析的日志)

Listening on port a 5435

sessionCreated==(0×013E8D89: nio socket, server, /127.0.0.1:1188 => /127.0.0.1:5435)

run decode!!!

in.remaining() == 4

没有不完整数据

数据包长69 bufTmp.remaining() ==4

数据还不完整

剩余数据保存到Session!!!4字节 00:00:00:45

run decode!!!

in.remaining() == 8

尚有不完整数据:00:00:00:45

数据包长69 bufTmp.remaining() ==12

数据还不完整

剩余数据保存到Session!!!12字节 00:00:00:45:80:00:00:00:00:00:00:00

run decode!!!

in.remaining() == 57

尚有不完整数据:00:00:00:45:80:00:00:00:00:00:00:00

数据包长69 bufTmp.remaining() ==69

hexdata:00:00:00:45:80:00:00:00:00:00:00:00:00:00:00:7a

00:00:00:1d:68:74:74:70:3a:2f:2f:31:32:37:2e:30

2e:30:2e:31:3a:35:34:33:35:2f:58:64:70:70:59:61

6e:00:00:00:10:63:02:00:6d:00:04:65:63:68:6f:04

79:79:79:79:7a

(上面是 合并之后得到的数据包)

ps: 也可以使用Apache mina 提供的statemachine来处理类似的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值