本文转自: http://blog.sina.com.cn/s/blog_46e73e770100b0cb.html
在上一篇《 基于mina的socket server——数据接收 》中介绍了如果通过mina构建一个简单的socket server来接收数据。通常有接收,就需要用到数据发送,也就是收到一个消息,处理后再发送一个回应 的消息给 对方。在数据接收的基础上,现在补充数据发送部分。
1、创建要发送的socket消息对象。假设在接收到消息后,处理后返回的消息结构为
:1字节的版本号+2字节的协
议类型+1字节的结果类型。因此对应的socket消息对象类似如下:
public class ReplayMessage implements Serializable{ private byte version; private short protocolType; private byte resultCode; public ReplayMessage(){ } ...//getter and setter method //返回消息总长度 public int getLength(){ return 4; } public byte[] toBytes(){ ByteBuffer buff = ByteBuffer.allocate(4); buff.put(this.version); buff.putShort(this.protocolType); buff.put(resultCode); return buff.array(); } }
假设resultCode=0表示成功,resultCode=1表示失败。(更复杂的含义或消息结构可以根据自己的实际情况来定义)。
需要特别注意的是
,
在该消息中增加一个方法:toBytes。toBytes方法用来把消息体的各个字段按照协议封装到
byte数组中,以便发送时需要。因为socket发送数据时,最基本的单位就是byte,因此我
们把要发送的消
息就封装成byte数组,就更便于发送。
getLength方法返回消息体长度。
其实,更好的做法是让要发送的消息类实现一个接口
,
接口中定义toBytes方
法
,
每个消息类都实现该接口
即
可。还可以通过抽象类把一些有共性的地方集中,然后在
各个
子类
中实现不同的
部分
。
2、接下来创建用来封装要发送数据的编码器类,也就是要新建一个类,并实现mina中的MessageE
ncoder接
口。
public ReplayMessageEncoder<T extends ReplayMessage> implements MessageEncoder{ public ReplayMessageEncoder(){ } @Override public void encode(IoSession session, T message, ProtocolEncoderOutput out) throws Exception { IoBuffer buff = IoBuffer.allocate(message.getLength()); buff.setAutoExpand(true); buff.put(message.toBytes()); buff.flip(); out.write(buff); } }
encode方法就是重写的MessageEncoder
接口中的方法。在该方法中,我们调用返回消息类中的getLength方法得
到消息长度用来分配buff空间,然后调用返回消息类中的toBytes方法把
消息转换为byte数组,然后写到协议
编码输出对象中。
3、修改协议解析工厂,把要发送的消息类与其对应的编码器注册
到解复用协议工厂中。也就是修改《
基于mina的socket server——数据接收
》中的TestMessageCodecFactor
类,修改后的TestMessageCodecFact
ory如
下:
public class TestMessageCodecFactory extends DemuxingProtocolCodecFac tory{ public TestMessageCodecFactory (){ super.addMessageDecoder(TestMessageDecoder .class); super.addMessageEncoder(ReplayMessage.class,ReplayMessageEncoder.class); } }
4、修改TestServerSessionHandler
中的messageReceived方法,增加发送消息功能。修改后的messageReceived方法如下:
public void messageReceived(IoSession session, Object message) throws Exception { if(message instanceof TestMessage){ TestMessage msg = (TestMessage )message; //在此得到的msg就是通过socket接收到的且已经安装协议解析好的对象了。在此仅打印出而已 System.out.println("received message content:"+msg.getMsgBody()); //增加发送消息 if(msg.getMsgBody().equalsIgnoreCase("hello")){ ReplayMessage msg = new ReplayMessage(); msg.setVersion((byte)1); msg.setProtocolType((short)1); msg.setResultCode((byte)0); session.write(msg); } } }
也就是,当接收到的消息体内容为“hello”是,就返回一个成功的消息。
自此,一个基于mina的socket数据发送就完成了,其他的不需要修改,重新编译启动,试着发
送一个消息体为“hello”的消息到该socket server,应该就能接收到来自于socket server的回复消息
了。