打算用mina以协议的方式一次传输大文件,其实即便是一次传输mina也会给分段传送,现在我以异步的方式传送。出现的问题是,接收端接收到的内容,不是发送过来的顺序,这可怎么办啊,这样我接收到的内容根本不知道怎么处理,原因是mina给你随机分的片,我是没办法控制的,也没办法加序号,这怎么办呢?
解决方案 »
- java 远程登录
- snmp读取交换机有多少设备在线
- jdk1.5.0_09设置环境变量问题,高手帮忙。
- 高手请进!帮我看一下我这个JAVA连接mysql的程序有什么问题
- 有多少服务端程序是用java写的?java程序这么慢能不能担当服务器程序的角色?
- 在for循环里面 怎么暂停一下~~就是程序语句执行停顿一定的时间~~
- 为何我的java线程会引起oracle的TNSLSNR.EXE进程占用100%的CPU
- 新手求助:父类与子类对象的转换
- 使用Java的勇气号都动不了啦,放弃java吧
- Sun 公司的JAVA培训如何?
- process进程堵塞问题
- java如何实现鼠标拖动绘制虚框矩形,在画出矩形后矩形虚拟边框消失,矩形中间填充颜色?.
基于TCP协议是不可能的,除非是你的代码有问题.
public class GroupUMessageDecoder implements MessageDecoder {
private static final Logger logger = org.slf4j.LoggerFactory.getLogger(MessageDecoder.class);
private Charset charset; public GroupUMessageDecoder(Charset charset) {
this.charset = charset;
} /**
* 检查给定的IoBuffer是否适合解码
*/
public MessageDecoderResult decodable(IoSession session, IoBuffer in) {
// 报头长度==6
if (in.remaining() < 6) {
return MessageDecoderResult.NEED_DATA;
} // tag正常
short tag = in.getShort();
if (tag == 1 || tag == 2) {
logger.info("请求标识符:" + tag);
} else {
logger.error("未知的解码类型....");
return MessageDecoderResult.NOT_OK;
} // 真实数据长度
int len = in.getInt();
int remainLen = in.remaining();
logger.info("dataLength:{}, remainLength:{}", len, remainLen);
if (remainLen < len) {
return MessageDecoderResult.NEED_DATA;
}
return MessageDecoderResult.OK;
} public MessageDecoderResult decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
logger.info("解码:" + in.toString());
CharsetDecoder decoder = charset.newDecoder();
BaseMessage message = null;
short tag = in.getShort(); // tag
int len = in.getInt(); // length
logger.info("解码数据长度:" + len); byte[] temp = new byte[len];
in.get(temp); // 数据区 // ===============解析数据做准备======================
IoBuffer buf = IoBuffer.allocate(400).setAutoExpand(true);
buf.put(temp);
buf.flip(); // 为获取基本数据区长度做准备 if (tag == 1) { // 简单类型Message
SimpleMessageResponse resp = new SimpleMessageResponse();
String txtMessage = "";
if (len > 0) {
txtMessage = buf.getString(len, decoder);
}
resp.setTxtMessage(txtMessage);
message = resp;
}
else if (tag == 2) {
TxtImageMessageRequest resp = new TxtImageMessageRequest();
//数据部分
// 1, 文字长度描述(32bit) + 文字内容
int txtLen = buf.getInt();//文字的长度
String txtMessage = "";
if (len > 0) {
txtMessage = buf.getString(txtLen, decoder);
}
resp.setTxtMessage(txtMessage);
// 2, 图片数量
int imageNum = buf.getInt();
logger.info("received TxtMessage length:{}, message:{}, imageNum:" + imageNum, txtLen, txtMessage);
// 2, 图片部分: 图片名称长度描述 图片长度. 图片在文字内容的位置(32bit) + 图片长度描述(32bit) + 图片数据
while (imageNum-- > 0) {
int imageNameLength = buf.getInt();//图片的名称的长度
if (imageNameLength <= 0 )
break;
String imageName = buf.getString(imageNameLength, decoder);
if (imageName == null || "".equals(imageName))
break;
logger.info("imageName:{}" , imageName);
int imagePosition = buf.getInt();//图片的位置
int imageLength = buf.getInt();//图片的长度
if (imageLength <= 0)
break;
byte[] imageData = new byte[imageLength];
buf.get(imageData);
MessageImageInfo ii = new MessageImageInfo();
ii.setImageName(imageName);
ii.setImagePositionInTxt(imagePosition);
ii.setImageData(imageData);
resp.addImageInfo(ii);
message = resp;
break;
}
}
out.write(message);
// ================解码成功=========================
return MessageDecoderResult.OK;
} public void finishDecode(IoSession session, ProtocolDecoderOutput out)
throws Exception {
}
}public class GroupUMessageEncoder implements MessageEncoder<BaseMessage> {
private static final Logger log = org.slf4j.LoggerFactory.getLogger(GroupUMessageEncoder.class);
private Charset charset; public GroupUMessageEncoder(Charset charset) {
this.charset = charset;
} public void encode(IoSession session, BaseMessage message,
ProtocolEncoderOutput out) throws Exception {
IoBuffer buf = IoBuffer.allocate(400).setAutoExpand(true); // ===========SimpleMessageRequest 编码数据区===============
if (message instanceof SimpleMessageRequest) {
SimpleMessageRequest req = (SimpleMessageRequest) message;
buf.putShort((short) req.getTag());
int dataLength = req.getLen(charset);
buf.putInt(dataLength);
log.info("SimpleMessageRequest dataLength:" + dataLength);
buf.putString(req.getTxtMessage(), charset.newEncoder());
log.info("SimpleMessageRequest 编码完毕:" + buf.toString());
}
// ===========TxtImageMessageRequest 编码数据区===============
if (message instanceof TxtImageMessageRequest) {
TxtImageMessageRequest req = (TxtImageMessageRequest) message;
buf.putShort((short) req.getTag());
int dataLength = req.getLen(charset);
buf.putInt(dataLength);
System.out.println("dataLength:" + dataLength);
//数据部分
// 1, 文字长度描述(32bit) + 文字内容
int txtLength = req.getTxtMessage().getBytes(charset).length;
buf.putInt(txtLength);
buf.putString(req.getTxtMessage(), charset.newEncoder());
// 2, 图片数量
buf.putInt(req.getImageNum());
// 3, 图片部分: 图片名称长度描述 图片长度. 图片在文字内容的位置(32bit) + 图片长度描述(32bit) + 图片数据
if (req.getImageList() != null && req.getImageList().size() > 0) {
for (MessageImageInfo mii : req.getImageList()) {
if (mii.getImageData() == null || mii.getImageData().length == 0){
log.warn("TxtImageMessageRequest Encode: image no data");
continue;
}
int imageNameLength = mii.getImageName().getBytes(charset).length;
buf.putInt(imageNameLength); //图片名称长度
buf.putString(mii.getImageName(), charset.newEncoder()); //图片名称
buf.putInt(mii.getImagePositionInTxt()); //图片位置
buf.putInt(mii.getImageData().length); //图片数据长度
buf.put(mii.getImageData()); //图片数据
}
}
log.info("TxtImageMessageRequest编码完毕:" + buf.toString());
} buf.flip();
out.write(buf);
}
}
解码的时候, 你要确定你收到的数据是你Client发送的全部部分. 如果只是部分, 你就没法解码了. 比如发送图片, 接收一半就去解码成一张图片, 肯定就是个烂图.
当然, 如果是传输大文件, 就不必要全部接收了在写磁盘去, 可以边接收,边写, 就不用占用太多内容.