首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 互联网 >

练练手,用mina2.0筹建一个nio客户端

2012-09-16 
练练手,用mina2.0搭建一个nio客户端练练手,用mina2.0搭建一个nio客户端,连接服务器。mina2用NioSocketConne

练练手,用mina2.0搭建一个nio客户端
练练手,用mina2.0搭建一个nio客户端,连接服务器。

mina2用NioSocketConnector连接,以前mina1的时候叫SocketConnector,现在SocketConnector是一个接口,要注意下区别。

需要的东西,一个handler来处理各种io事件,一个ProtocolCodecFactory来对消息进行编码(ProtocolEncoder)和解码(ProtocolDecoder)。此外还需要自己编写一个MessageHandler来处理收到的信息。

编写一个类比如SxdHandler继承自IoHandlerAdapter,实现messageReceived,sessionCreated等方法。

编写一个类比如SxdCodecFactory继承自ProtocolCodecFactory来返回单例的编码者和解码者。

编写一个类比如SxdEncoder继承自ProtocolEncoder,来对自己的信息编码,编为IoBuffer输出。

编写一个类比如SxdDecoder继承自ProtocolDecoder,来对收到的字节缓冲区进行解析,解析成自己的消息放到ProtocolDecoderOutput,这样iohandler的messageReceived方法被调用,这个时候找到该信息对应的messagehandler,来进行消息处理。

程序流程,先创建一个NioSocketConnector,设置handel类,连接目标服务器,创建协议分析器到过滤器链中,然后就是等待操作了。
当连接打开时,iohandler的sessionOpened方法被调用,在这里发送比如登陆服务器的消息就行了,当收到消息,messageReceived会被调用,找到这个消息的handler,开始处理就行了。

下面是创建client实例代码:

NioSocketConnector conn = new NioSocketConnector();conn.setConnectTimeoutMillis(30*1000l);conn.setHandler(new SxdHandler());ConnectFuture cf = conn.connect(new InetSocketAddress("8x007.xd.com", 8002));conn.getFilterChain().addLast("codec", new ProtocolCodecFilter(new SxdCodecFactory()));conn.getFilterChain().addLast( "logging", new LoggingFilter() );cf.awaitUninterruptibly();cf.getSession().getCloseFuture().awaitUninterruptibly();conn.dispose();


关键的一点如何设计消息,消息分C->S的发送消息(CGMessage)和S->C的接受信息(GCMessage),
消息最后是通过字节流在网上传输的,因此需要知道消息的长度,然后是类型,最后是数据客户端和服务端按照相同协议解析和发送消息。
这是消息的抽象定义,提供了读写方法。
import java.io.UnsupportedEncodingException;import org.apache.mina.core.buffer.IoBuffer;public abstract class Message {protected IoBuffer buff;public byte module;public byte func;public Message(byte module, byte func){this.module = module;this.func = func;};int length = 0;public void write(){if(buff == null){buff = IoBuffer.allocate(0).setAutoExpand(true);}buff.clear();buff.putInt(0);//先占位,再buff.put(module);buff.put(func);writeImpl();length = buff.position() - 4;buff.putInt(0, length);//buff.capacity(length + 4);buff.flip();}public abstract void writeImpl();  public  void read(){length = buff.getInt() - 4;buff.get();buff.get();this.readImpl();}public abstract void readImpl();  public IoBuffer getBuff() {return buff;}public void setBuff(IoBuffer buff) {this.buff = buff;}protected void writeString(String s){buff.putShort((short) s.length());try {buff.put(s.getBytes("UTF-8"));} catch (UnsupportedEncodingException e) { e.printStackTrace();}}protected void writeInt(int i){buff.putInt(i);}protected void writeShort(short s){buff.putShort(s);}public int getLength() {return length + 4;}protected String readString(){short len = buff.getShort();byte[] bs =new byte[len];buff.get(bs);try {return new String(bs, "UTF-8");} catch (UnsupportedEncodingException e) { e.printStackTrace();return new String(bs);}}protected int readInt(){return buff.getInt();}protected short readShort(){return buff.getShort();}protected byte readByte(){return buff.get();}protected long readLong(){return buff.getLong();}public String getKey(){return module+"_"+func;}} 

针对GCMessage,还需要编写一个MessageHandler来处理这个message,在统一的一个类中进行注册和查找。

附件是练手写的连接神仙道服务器的例子,可以收到服务器发来的玩家基本信息。

热点排行