socket 与 mina 交互数据
来源:互联网 发布:联通首选网络类型 编辑:程序博客网 时间:2024/05/26 02:55
之前网上查了些资料,有些blog说mina做服务端,socket做客户端,没法用DemuxingProtocolCodecFactory,只能用TextLineCodecFactory协议解析,但要是传文件,这个东东根本就没用,事实上,服务器很大可能是要传文件的,mina做服务端,客户端可能是不同的。比如用mina的客户端写,用nio自己写,用socket自己写,用C语言自己写。
本次测试例子:使用socket传送较长字符串,如果传送文件,也是一样的过程,先将字符串或者文件转换成byte数组
其实如果理解mina的协议解析的话就会非常简单处理这些解码:
大体思想:协议一般有头信息 告诉程序需要读取多少字节,程序就可以不断读取了,知道在哪个字节时候就不用再往后读了。
IoBuffer读取的时候就像一个管道,读取了这部分数据,这部分数据就没有,其实IO流就是这样
Socket客户端:
package com.test;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.InetSocketAddress;import java.net.Socket;import java.net.UnknownHostException;import java.nio.charset.Charset;import org.apache.mina.core.future.ConnectFuture;import org.apache.mina.core.service.IoConnector;import org.apache.mina.core.session.IoSession;import org.apache.mina.filter.codec.ProtocolCodecFilter;import org.apache.mina.filter.codec.textline.TextLineCodecFactory;import org.apache.mina.transport.socket.nio.NioSocketConnector;public class client {public static void main(String[] args) throws Exception{Socket socket = new Socket("127.0.0.1",9123);OutputStream os = socket.getOutputStream();String str = "";for(int i=0;i<100;i++){str = str + "我们都是中国人啊!";}byte[] bytes = str.getBytes("utf-8");System.out.println("数据byte长度:"+bytes.length);os.write(i2b(bytes.length));os.write(bytes);os.flush();InputStream is = null;is = socket.getInputStream();byte[] intByte = new byte[4];is.read(intByte);int msgLength = b2i(intByte);System.out.println("int:"+msgLength);int readPosition = 0;byte[] byteArray = new byte[msgLength];while(readPosition < msgLength){int value = is.read(byteArray, readPosition, msgLength-readPosition);if(value == -1){break;}readPosition += value;}System.out.println(new String(byteArray,"utf-8"));System.out.println("byteArray Length:"+byteArray.length+" string Length:"+new String(byteArray,"utf-8").length());if(os != null){os.close();}if(is != null){is.close();}}// 网上抄来的,将 int 转成字节public static byte[] i2b(int i) {return new byte[] { (byte) ((i >> 24) & 0xFF),(byte) ((i >> 16) & 0xFF), (byte) ((i >> 8) & 0xFF),(byte) (i & 0xFF) };}public static int b2i(byte[] b) {int value = 0;for (int i = 0; i < 4; i++) {int shift = (4 - 1 - i) * 8;value += (b[i] & 0x000000FF) << shift;}return value;}}socket先发送测试数据,然后接收服务端返回的数据
package com.test;import java.io.File;import java.io.FileOutputStream;import java.nio.charset.Charset;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;import org.apache.mina.filter.codec.demux.MessageDecoder;import org.apache.mina.filter.codec.demux.MessageDecoderResult;public class BaseMessageDecoder implements MessageDecoder {AttributeKey CONTEXT = new AttributeKey(getClass(),"context");/** * 是否适合解码 * */public MessageDecoderResult decodable(IoSession session, IoBuffer in) {// TODO Auto-generated method stubreturn MessageDecoderResult.OK;}/** * 数据解码 * */public MessageDecoderResult decode(IoSession session, IoBuffer in,ProtocolDecoderOutput outPut) throws Exception {// TODO Auto-generated method stubContext context = (Context) session.getAttribute(CONTEXT);// TODO Auto-generated method stubIoBuffer buffer = in;if(context == null || !context.init){IoBuffer b = buffer.get(new byte[4]);byte[] intByte = b.array();int num = b2i(intByte);System.out.println("长度:"+num);context = new Context();context.number = num;context.position = 0;context.byteArray = new byte[num];context.init = true;while(buffer.hasRemaining()){byte c = buffer.get();context.byteArray[context.position] = c;context.position++;}}else{while(buffer.hasRemaining()){byte c = buffer.get();context.byteArray[context.position] = c;if( context.position == context.number-1){System.out.println(new String(context.byteArray,"utf-8"));IoBuffer buff = IoBuffer.allocate(1024).setAutoExpand(true);buff.put(i2b(context.number));buff.put(context.byteArray);buff.flip();outPut.write(buff);return MessageDecoderResult.OK;}context.position++;}}session.setAttribute(CONTEXT,context);return MessageDecoderResult.NEED_DATA;}/** * 解码完成 * */public void finishDecode(IoSession session, ProtocolDecoderOutput outPut)throws Exception {// TODO Auto-generated method stub}public static int b2i(byte[] b) {int value = 0;for (int i = 0; i < 4; i++) {int shift = (4 - 1 - i) * 8;value += (b[i] & 0x000000FF) << shift;}return value;}public static byte[] i2b(int i) {return new byte[] { (byte) ((i >> 24) & 0xFF),(byte) ((i >> 16) & 0xFF), (byte) ((i >> 8) & 0xFF),(byte) (i & 0xFF) };}class Context {public Integer number;public byte[] byteArray;public Integer position;public boolean init;}}因传送字符串较长,执行多次调用decode方法,需要中间变量记住之前的部分字段值。
IoBuffer buff = IoBuffer.allocate(1024).setAutoExpand(true);
buff.put(i2b(context.number));
buff.put(context.byteArray);
buff.flip();
outPut.write(buff);
这段代码本应该写在BaseMessageEncoder的encode方法中,但出于我并没有在服务端需要这些字符串值,所以直接将数据方法IoBuffer,服务端直接写回客户端
测试数据OK。
源代码
- socket 与 mina 交互数据
- C/S通信交互之Cocos2dx使用BSD Socket与Mina手机网游通信框架
- Socket异常与MINA异常
- 【C/S通信交互之Socket篇】Cocos2dx(Client)使用BSD Socket与Mina(Server)手机网游通信框架!
- 【C/S通信交互之Socket篇】Cocos2dx(Client)使用BSD Socket与Mina(Server)手机网游通信框架
- 【C/S通信交互之Socket篇】Cocos2dx(Client)使用BSD Socket与Mina(Server)手机网游通信框架!
- 【C/S通信交互之Socket篇】Cocos2dx(Client)使用BSD Socket与Mina(Server)手机网游通信框架!
- 【C/S通信交互之Socket篇】Cocos2dx(Client)使用BSD Socket与Mina(Server)手机网游通信框架!
- 【C/S通信交互之Socket篇】Cocos2dx(Client)使用BSD Socket与Mina(Server)手机网游通信框架!
- Mina自定义协议-实现数据交互
- socket编程交互数据
- Linux用户态与内核态交互数据---socket函数
- 浅谈iOS与Socket交互:数据异常处理
- c++与web交互socket该发送的协议数据
- nodejs 使用socket.io与网页实时数据交互
- Socket与SMTP交互
- nio/mina(四)客户端socket与mina服务端通信
- Apache Mina Socket 与单片机通讯
- maven 插件配置汇总小计
- PHP 调用java
- 黑马程序员——使用equals实现对象的比较
- linux解压 tar命令
- 一段最短的代码,用上js所有关键字
- socket 与 mina 交互数据
- Memcached--分布式缓存
- PHP cookie session
- webm convert
- 算法导论-第19章-二项堆
- Android 中自定义属性
- 《ORACLE PL/SQL编程详细》
- Android常用命令
- [linux常用命令] 1、文件内容显示